C# 队列的InvalidCastException<;字符串>;在多线程应用程序中

C# 队列的InvalidCastException<;字符串>;在多线程应用程序中,c#,string,exception,.net,C#,String,Exception,.net,输出缓冲区声明为类变量 private Queue<String> __OutputBuffer = new Queue<String>(); private void ProcessOutput() { if (__OutputBuffer.Count > 0 && !String.IsNullOrEmpty(__OutputBuffer.Peek())) { object _Item = __OutputBuff

输出缓冲区声明为类变量

private Queue<String> __OutputBuffer = new Queue<String>();
private void ProcessOutput()
{
    if (__OutputBuffer.Count > 0 && !String.IsNullOrEmpty(__OutputBuffer.Peek()))
    {
        object _Item = __OutputBuffer.Dequeue();

        if(_Item is String)
        {
            try
            {
                Browser.DocumentText += "<span style='font-family: Tahoma; font-size: 9pt;'>" + _Item + "</span>"; 
                //Exception On Line Above!
            }
            catch (Exception) { }
        }
    }
}   
处理队列

private Queue<String> __OutputBuffer = new Queue<String>();
private void ProcessOutput()
{
    if (__OutputBuffer.Count > 0 && !String.IsNullOrEmpty(__OutputBuffer.Peek()))
    {
        object _Item = __OutputBuffer.Dequeue();

        if(_Item is String)
        {
            try
            {
                Browser.DocumentText += "<span style='font-family: Tahoma; font-size: 9pt;'>" + _Item + "</span>"; 
                //Exception On Line Above!
            }
            catch (Exception) { }
        }
    }
}   
我得到了无效的强制转换异常,下面是获取异常时_项的内容

**此外,以下情况会导致异常。。。所以我怀疑这是队列中字符串的内容

队列
不是线程安全的,而
System.Timers.Timer
在随机池线程上触发其事件。这是调用
ProcessOutput
的地方,也是调用
\u OutputBuffer.Dequeue()
和访问
Browser.DocumentText
的地方


您可以使用
保护
\u OutputBuffer
不受并发访问(对于
出列
入列
),或者改用
并发队列
。但是,您需要将
浏览器.DocumentText
分配封送到UI线程,例如使用
控件.Invoke
控件.BeginInvoke
正如Noserio所说,
队列
不是线程安全的,但是,如果您不希望在项目中使用锁定,并且正在使用.NET 4.0或更新版本,则可以使用线程安全的类

您需要进行一些更改,例如没有
Peek
Dequeue
方法,而必须使用
TryPeek
TryDequeue
。但是它不需要太多的主要更改,它甚至可以让您进行一些优化,因为如果队列为空,这两个try方法将返回
false
,因此您不再需要
计数
检查

private void ProcessOutput()
{
    string output;
    if (__OutputBuffer.TryDequeue(out output) && !String.IsNullOrEmpty(output))
    {
        try
        {
            Browser.DocumentText += "<span style='font-family: Tahoma; font-size: 9pt;'>" + output  + "</span>"; 
        }
        catch (Exception) { } // <--- Blindly catching exceptsions is almost never the right thing to do.
    }
} 
private void ProcessOutput()
{
字符串输出;
if(uuu OutputBuffer.TryDequeue(输出)&!String.IsNullOrEmpty(输出))
{
尝试
{
Browser.DocumentText+=“”+输出+“”;
}

使用计时器捕获(异常){}/被认为是多线程的。 您每100毫秒有一个新线程,这可能会导致您在退出队列时遇到竞争条件

使用:

private ConcurrentQueue\uuu OutputBuffer=new ConcurrentQueue();
私有void ProcessOutput()
{
字符串_项;
if(uu OutputBuffer.TryDequeue(out项目))
{
尝试
{
Browser.DocumentText+=“”+\u Item+“”;
//上面一行出现异常!
}
捕获(异常){}
}
}

队列
不是线程安全的,并且
系统.计时器.Timer
在随机池线程上触发其事件,这就是调用
ProcessOutput
的地方,也是访问
浏览器.DocumentText
的地方。我已经解决了这个问题。我在浏览器上使用了.Invoke。不确定我的解决方案是否很好,请告知。为什么您是否
Peek
然后
Dequeue
?,如果您的队列中有空字符串,您将停止处理,因为它将永远不会退出队列。祝贺10K代表,感谢您的回答:)
private ConcurrentQueue<String> __OutputBuffer = new ConcurrentQueue<String>();

private void ProcessOutput()
{
    string _Item;
    if (__OutputBuffer.TryDequeue(out _Item))
    {
         try
         {
              Browser.DocumentText += "<span style='font-family: Tahoma; font-size: 9pt;'>" + _Item + "</span>";
             //Exception On Line Above!
         }
         catch (Exception) { }
    }
}