Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.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# 多线程环境问题_C#_Wpf_Multithreading - Fatal编程技术网

C# 多线程环境问题

C# 多线程环境问题,c#,wpf,multithreading,C#,Wpf,Multithreading,我有一个WPF控件,它正在处理、呈现和显示在我的应用程序的主线程中。控件将数千个数据点上传到名为“层”的对象中的视图中。下面是对象/类层次结构的大致描述: public class WPFControl{ private List<Layer> myLayers; public List<Layer> MyLayers{ get{ return myLayer;} } ... } public class Laye

我有一个WPF控件,它正在处理、呈现和显示在我的应用程序的主线程中。控件将数千个数据点上传到名为“层”的对象中的视图中。下面是对象/类层次结构的大致描述:

public class WPFControl{

   private List<Layer> myLayers;

   public List<Layer> MyLayers{
      get{ return myLayer;}
   }       

   ...
}

public class Layer{
   private List<DataPoint> myDataPoints;

   public List<DataPoint> MyDataPoints{
        get{ return myDataPoints;}
   }

   ...
}

public class DataPoint{
   ....
}
WPF控件触发此错误:

The calling thread cannot access this object because a different thread owns it
我想,好吧,我可以这样使用调度器:

myWpfControl.Dispatcher.Invoke((Action)
 (()=>{                                   
    myWpfControl.MyLayers.Add(layerCreatedInOtherThread);
 })
 );
但我总是犯同样的错误。你知道我该如何解决这个问题吗?

使用一个线程,你可以在另一个线程上运行一个任务,然后当任务完成时,你可以从UI线程访问结果

private System.ComponentModel.BackgroundWorker bgWorker;
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);

 //Start the work
 bgWorker.RunWorkerAsync(null) //you can send an argument instead of null
做这项工作

    private void backgroundWorker1_DoWork(object sender, 
        DoWorkEventArgs e)
    {   
        // Get the BackgroundWorker that raised this event.
        BackgroundWorker worker = sender as BackgroundWorker;

        // Assign the result of the computation 
        // to the Result property of the DoWorkEventArgs 
        // object. This is will be available to the  
        // RunWorkerCompleted eventhandler.
        e.Result = CreateLayerInOtherThread(); //if you sent an arg instead of null it as availalbe in e.Argument and can be cast from object.
    }
完成后获得结果。它在UI线程上运行,因此您可以更新它

    private void bgWorker_RunWorkerCompleted(
        object sender, RunWorkerCompletedEventArgs e)
    {
        // First, handle the case where an exception was thrown. 
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
        }
        else if (e.Cancelled)
        {
            // Next, handle the case where the user canceled  
            // the operation. 
            // Note that due to a race condition in  
            // the DoWork event handler, the Cancelled 
            // flag may not have been set, even though 
            // CancelAsync was called.


        }
        else
        {
            // Finally, handle the case where the operation  
            // succeeded.
            Layer myLayer = (Layer)e.Result;
            myWpfControl.MyLayers.Add(myLayer);
        }


    }

你不能这样做。UI不是数据。在后台线程中获取数据,和数据绑定您的UI,而不是试图在过程代码中操作它。
我正在另一个线程中创建该层对象。
显示代码。查看优先级绑定和后台工作使用BackgroundWorker或TPL和具有同步的任务Context@Harrison为什么不让这成为一个完整的答案,而不是一个简单的答案注释?这将不起作用,因为后台线程正在创建
DispatcherObject
-派生对象,当然这些对象与“主”dispatcher没有关联。@HighCore。我不知道这为什么行不通,我不理解你的评论。BackgorundWorker的目的是在另一个线程上运行工作,然后在完成时访问调度程序。你建议我删除这个答案吗?你有什么建议作为解决方案。我要说清楚,OP可能正在后台线程中创建
UI
元素,这是行不通的。他将UI和数据混合在一起,因此被迫采用单线程方案。您无法在后台线程中创建UI元素并期望它们在另一个线程的调度程序中工作。我建议的解决方案一如既往地是MVVM和数据绑定,而不是类似winforms的方法。@HighCore我没有意识到这是一个
UIElement
。从他的代码看,他似乎正在创建一个层,然后将其提供给
UIElement
的属性。我弄错了吗?“这还不可能吗?”哈里森和HighCore——我希望原始海报能回来,澄清他意图中的不确定性。我想知道答案是什么,因为我计划在将来的某个时候做类似的事情。
    private void bgWorker_RunWorkerCompleted(
        object sender, RunWorkerCompletedEventArgs e)
    {
        // First, handle the case where an exception was thrown. 
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
        }
        else if (e.Cancelled)
        {
            // Next, handle the case where the user canceled  
            // the operation. 
            // Note that due to a race condition in  
            // the DoWork event handler, the Cancelled 
            // flag may not have been set, even though 
            // CancelAsync was called.


        }
        else
        {
            // Finally, handle the case where the operation  
            // succeeded.
            Layer myLayer = (Layer)e.Result;
            myWpfControl.MyLayers.Add(myLayer);
        }


    }