为什么SynchronizationContext.Current空?SynchronizationContext、Current

2023-09-03 03:51:37 作者:凉城梦境空人心

错误:对象引用不设置到对象的实例

下面工作的算法。 我试了一下,然后我删除了 WinForm的的项目到其他目录 SynchronizationContext.Current 。 为什么呢?

 的SynchronizationContext uiCtx = SynchronizationContext.Current;

私人无效backgroundWorker1_DoWork(对象发件人,DoWorkEventArgs E)
{
    INT [] makeSelfMoves =新INT [4];

    锁(重播)
    {
        //数应大于2
        的foreach(KeyValuePair< INT,INT []>在重播项)
        {
            makeSelfMoves =重播[item.Key]
            codeFile.ExecuteAll(makeSelfMoves [0]
              makeSelfMoves [1],makeSelfMoves [2],makeSelfMoves [3]);

            //我这里得到的错误。 uictx为null
            uiCtx.Post(O =>
            {
                PrintPieces(codeFile.PieceState());
            }, 空值);

            System.Threading.Thread.Sleep(1000);
        }
    }
}
 

解决方案

您code关键取决于究竟在何时何地你的类运行的构造函数。 SynchronizationContext.Current将空时:

你的类对象被创建太早,在你的code创建窗体类的实例或调用Application.Run()在main()。这时候,当前成员设置为WindowsFormsSynchronizationContext,知道如何元帅的消息循环调用这个类的一个实例。通过移动你的对象实例化code到主窗体构造函数解决这个问题。

你的类对象上比主UI线程以外的任何线程创建。只有在一个WinForms应用程序的UI线程可以封送调用。通过增加一个构造函数类这种说法诊断这样的:

  Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
 

也加入这一行Program.cs中的Main()方法。如果在输出窗口中显示的值不同,它不会起作用。通过移动你的对象实例化code到,再次,主窗体构造函数,所以你可以确保它运行在UI线程上解决这个问题。

Error: Object reference not set to an instance of an object.

The algorithm below works. I tried it, then I removed the Winform project to another directory and SynchronizationContext.Current is null. Why?

SynchronizationContext uiCtx = SynchronizationContext.Current;  

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    int[] makeSelfMoves = new int[4];

    lock (replay)
    {
        // count should be more than 2
        foreach (KeyValuePair<int, int[]> item in replay)
        {              
            makeSelfMoves = replay[item.Key];
            codeFile.ExecuteAll(makeSelfMoves[0],
              makeSelfMoves[1], makeSelfMoves[2], makeSelfMoves[3]);

            // i get the error here. uictx is null
            uiCtx.Post(o =>
            {
                PrintPieces(codeFile.PieceState());
            }, null);                               

            System.Threading.Thread.Sleep(1000);
        }
    }
}

解决方案

Your code critically depends on exactly when and where the constructor of your class runs. SynchronizationContext.Current will be null when:

your class object is created too soon, before your code creates an instance of the Form class or calls Application.Run() in Main(). That's when the Current member is set to an instance of WindowsFormsSynchronizationContext, the class that knows how to marshal calls with the message loop. Fix this by moving your object instancing code to the main form constructor.

your class object is created on any thread other than the main UI thread. Only the UI thread in a Winforms application can marshal calls. Diagnose this by adding a constructor to your class with this statement:

        Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);

Also add this line to the Main() method in Program.cs. It won't work if the displayed value in the Output window is different. Fix this by moving your object instancing code to, again, the main form constructor so you can be sure it runs on the UI thread.