Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/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# InvalidOperationException-对象当前正在其他地方使用_C#_.net_Winforms_Backgroundworker - Fatal编程技术网

C# InvalidOperationException-对象当前正在其他地方使用

C# InvalidOperationException-对象当前正在其他地方使用,c#,.net,winforms,backgroundworker,C#,.net,Winforms,Backgroundworker,我经历过,但没用 这里的情况不同。我在使用后台工作人员。First backgroundworker开始对用户的图像输入进行操作,在firstbackgroundworker_runworkercompleted()中,我正在调用其他3个backgroundworker algo1backgroundworker.RunWorkerAsync(); algo2backgroundworker.RunWorkerAsync(); algo3backgroundworker.RunWorker

我经历过,但没用

这里的情况不同。我在使用后台工作人员。First backgroundworker开始对用户的图像输入进行操作,在firstbackgroundworker_runworkercompleted()中,我正在调用其他3个backgroundworker

 algo1backgroundworker.RunWorkerAsync();
 algo2backgroundworker.RunWorkerAsync();
 algo3backgroundworker.RunWorkerAsync();
以下是每种类型的代码:

algo1backgroundworker_DoWork()
{
 Image img = this.picturebox.Image;
 imgclone = img.clone();
 //operate on imgclone and output it
}

algo2backgroundworker_DoWork()
{
 Image img = this.picturebox.Image;
 imgclone = img.clone();
 //operate on imgclone and output it
}
类似的操作在其他algo*BackgroundWorker_doWork()中完成

现在,有时我会得到“InvalidOperationException-对象当前正在其他地方使用”。这是非常武断的。我有时在algo1backgroundworker_工作中,有时在algo2backgroundworker_工作中,有时在Application.Run(new myWindowsForm())中得到这个


我不知道发生了什么事

看来您的后台工作人员正在试图同时访问相同的Windows窗体组件。这可以解释为什么失败是随机的

您需要使用
锁来确保不会发生这种情况,可能是这样的:

private object lockObject = new object();

algo1backgroundworker_DoWork()
{
    Image imgclone;
    lock (lockObject)
    {
        Image img = this.picturebox.Image;
        imgclone = img.clone();
    }

    //operate on imgclone and output it
}
请注意,我确保imgclone是此方法的本地版本-您肯定不想在所有方法中共享它

另一方面,所有方法都使用相同的lockObject实例。当BackgroundWorker方法进入其
lock{}
部分时,到达该点的其他方法将被阻止。因此,确保锁定部分中的代码是快速的非常重要


当您要“输出”处理后的图像时,也要小心,以确保不会对UI进行跨线程更新。检查是否有一种简洁的方法来避免这种情况。

在windows窗体中,不仅应该从单个线程访问控件,而且该线程应该是主应用程序线程,即创建控件的线程

这意味着在DoWork中,您不应该访问任何控件(不使用Control.Invoke)。所以在这里,您可以调用RunWorkerAsync传入您的映像克隆。在DoWork事件处理程序中,可以从DoWorkEventArgs.Argument中提取参数


只有ProgressChanged和RunWorkerCompleted事件处理程序才能与GUI交互。

GDI+内部有一个锁,防止两个线程同时访问位图。这不是一种阻塞类型的锁,它是一种“程序员做错了什么,我会抛出异常”类型的锁。您的线程正在爆炸,因为您正在所有线程中克隆图像(=访问位图)。您的UI线程正在爆炸,因为它正在试图绘制位图(=访问位图),同时线程正在克隆位图


您需要将位图的访问权限限制为仅一个线程。在启动BGW之前,在UI线程中克隆图像,每个BGW都需要自己的图像副本。在RunWorkerCompleted事件中更新PB的Image属性。这样会丢失一些并发性,但这是不可避免的。

当我试图从不同的线程访问主线程组件(PictureBox)时,我还使用了系统。InvalidOperationException:对象当前正在使用

MethodInvoker委托
解决了该问题

Invoke((MethodInvoker)(delegate ()
{
   var image = PictureBox.Image;
}));