Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# dispatcher invoke和combobox add项中出现空引用异常_C#_Multithreading_Combobox_Dispatcher - Fatal编程技术网

C# dispatcher invoke和combobox add项中出现空引用异常

C# dispatcher invoke和combobox add项中出现空引用异常,c#,multithreading,combobox,dispatcher,C#,Multithreading,Combobox,Dispatcher,我在主界面中有一个组合框,我将在其中显示一些可用的项目列表。我有一个后台工作线程,它将运行可用项目的时间检查 我在循环中运行这个线程,这样每次它都会检查可用项并更新到主UI组合框 这是我的代码片段 do { iNumberofReaders = 0; this.Dispatcher.BeginInvoke((Action)(() => { NumberOfCards.Items.Clear(); })); // // Co

我在主界面中有一个组合框,我将在其中显示一些可用的项目列表。我有一个后台工作线程,它将运行可用项目的时间检查

我在循环中运行这个线程,这样每次它都会检查可用项并更新到主UI组合框

这是我的代码片段

do
{
    iNumberofReaders = 0;

    this.Dispatcher.BeginInvoke((Action)(() =>
    {
        NumberOfCards.Items.Clear();
    }));

    //
    // Compose a list of the card readers which are connected to the
    // system and which will be monitored.
    //
    ArrayList availableReaders = this.ListReaders();

    this._states = new ReaderState[availableReaders.Count];

    for (int i = 0; i <= availableReaders.Count - 1; i++)
    {
        this._states[i].Reader = availableReaders[i].ToString();
    }

    result = (SmartcardErrorCode)UnsafeNativeMethods.GetStatusChange(
                this._context, 1000, this._states, this._states.Length);

    szAvailableReaders = new string[availableReaders.Count];
    for (int i = 0; i < availableReaders.Count; i++)
    {
        if (0 != this._states[i]._attribute)
        {
            szAvailableReaders[iNumberofReaders] = this._states[i]._reader;
            iNumberofReaders++;
        } // if
    } // for

    if (iNumberofReaders > 1)
    {
        this.Dispatcher.BeginInvoke((Action)(() =>
        {
            for (int j = 0; j < iNumberofReaders; j++)
            {
                NumberOfCards.Visibility =system.Windows.Visibility.Visible;
                NumberOfCards.Items.Add(szAvailableReaders[j]);
            } // for
        }));
    }
} while (SetThread);
(NumberOfCards是组合框)

我在dispatcher begin invoke的for循环中观察到了奇怪的行为。
有人能帮忙吗?

您正在一个单独的线程中修改
szAvailableReaders
数组,同时在GUI线程中读取它

首先,您应该考虑使用<代码>调用< <代码>,而不是<代码> RealNojk> <代码>,因为后者在GUI线程上排队请求,并且可以容易地创建一组队列操作,这将不必要地占用CPU。

此外,在线程之间共享数据时,最简单的做法是避免共享同一实例,而是为UI线程创建数据的不可变副本。这也适用于
iNumberofReaders
和线程之间共享的任何其他字段

换句话说,背景循环应该类似于:

do
{
    var availableReaders = this.ListReaders();

    // If you're only using `states` in this method,
    // make it a local variable:
    var states = availableReaders
        .Select(r => new ReaderState() { Reader = r.ToString() })
        .ToArray();

    // fill the data
    result = (SmartcardErrorCode)UnsafeNativeMethods
        .GetStatusChange(this._context, 1000, states, states.Length);

    // this is the important part: create a new instance of reader names.
    // LINQ also simplifies it a bit:        
    var availableReaders = states
        .Where(s => s._attribute != 0)
        .Select(s => s._reader)
        .ToList();

    // now that you have a local list, you can simply swap the field 
    // which is referencing it (since object assignments are atomic in .NET).
    // So the field gets a unique copy every time, and you can even go
    // an extra step forward by declaring it as a `ReadOnlyCollection<string>`:
    szAvailableReaders = new ReadOnlyCollection<string>(availableReaders);

    // Consider using `Invoke` here:        
    this.Dispatcher.BeginInvoke((Action)(() =>
    {
        NumberOfCards.Items.Clear();
        NumberOfCards.Items.AddRange(szAvailableReaders.ToArray());
    }));

} while (SetThread);
do
{
var availableReaders=this.ListReaders();
//如果在此方法中仅使用“states”,
//将其设置为局部变量:
var状态=可用的读卡器
.Select(r=>newreaderState(){Reader=r.ToString()})
.ToArray();
//填写数据
结果=(SmartcardErrorCode)非预防性方法
.GetStatusChange(此.u上下文,1000,状态,状态.Length);
//这是重要的部分:创建一个新的读卡器名称实例。
//LINQ还将其简化了一点:
var availableReaders=状态
。其中(s=>s.。_属性!=0)
.选择(s=>s.。\U读卡器)
.ToList();
//现在有了本地列表,您可以简单地交换字段
//它正在引用它(因为对象分配在.NET中是原子的)。
//因此,该字段每次都会得到一个唯一的副本,您甚至可以
//通过将其声明为“ReadOnlyCollection”而向前迈出了一步:
szAvailableReaders=新的只读集合(availableReaders);
/考虑在这里使用“调用”:
this.Dispatcher.BeginInvoke((操作)(()=>
{
NumberOfCards.Items.Clear();
NumberOfCards.Items.AddRange(szAvailableReaders.ToArray());
}));
}while(SetThread);

除此之外,这看起来是一个非常紧密的循环。我不知道你在读什么,但你不应该使用某种“readers list changed`事件,在这种情况下只更新组合吗?或者至少使用计时器每隔一秒左右轮询一次列表吗?

你的异常抛出在哪一行可能重复?是不是
NumberOfCards.Items.Add(szAvailableReaders[j]);
?我假设
NumberOfCards
是您的组合框…是的,我相信它在NumberOfCards.Items.Add中引发异常(szAvailableReaders[j]);我认为dispatcher begin invoke正在持续运行,尽管dispatcher begin invoke中的for loopmessagebox只显示一个值。它没有正确循环Groo这里我列出了所有连接到系统的智能卡读卡器。GetStatusChange将给我实际连接的读卡器。之后,我将它添加到字符串数组中,如果读卡器的数量rs大于1,只有我将其添加到组合框中。此循环将持续运行并检查连接的读卡器。我的目标是在每个循环中列出读卡器。然后清除组合框并再次添加连接的读卡器。是的,我知道了。但我不认为您的用户希望您的应用程序使用100%的单个CPU核心来更新组合框hund是的,我知道。你对此有什么建议,或者有什么方法可以让它工作吗?这里的代码没有修复你的
NullReferenceException
?对不起,我不能让它工作。我不明白你在那里做什么。(对不起,我不懂c).error是错误CS1061:“System.Collections.ArrayList”不包含“Select”的定义,并且找不到接受“System.Collections.ArrayList”类型的第一个参数的扩展方法“Select”(是否缺少using指令或程序集引用?)
do
{
    var availableReaders = this.ListReaders();

    // If you're only using `states` in this method,
    // make it a local variable:
    var states = availableReaders
        .Select(r => new ReaderState() { Reader = r.ToString() })
        .ToArray();

    // fill the data
    result = (SmartcardErrorCode)UnsafeNativeMethods
        .GetStatusChange(this._context, 1000, states, states.Length);

    // this is the important part: create a new instance of reader names.
    // LINQ also simplifies it a bit:        
    var availableReaders = states
        .Where(s => s._attribute != 0)
        .Select(s => s._reader)
        .ToList();

    // now that you have a local list, you can simply swap the field 
    // which is referencing it (since object assignments are atomic in .NET).
    // So the field gets a unique copy every time, and you can even go
    // an extra step forward by declaring it as a `ReadOnlyCollection<string>`:
    szAvailableReaders = new ReadOnlyCollection<string>(availableReaders);

    // Consider using `Invoke` here:        
    this.Dispatcher.BeginInvoke((Action)(() =>
    {
        NumberOfCards.Items.Clear();
        NumberOfCards.Items.AddRange(szAvailableReaders.ToArray());
    }));

} while (SetThread);