使用BackgroundWorker时C#中的线程问题

使用BackgroundWorker时C#中的线程问题,c#,multithreading,C#,Multithreading,请善良的灵魂解释一下为什么下面的psudocode不起作用。问题是,当从新线程调用时,无法在backgroundWorker(Monitor.TryEnter(bw))上获得锁。如果我从主UI线程调用它,它可以正常工作 谢谢 P 是否缺少监视器。请在if块末尾退出。 如果没有Monitor.Exit,则无论哪个线程首先成功执行Monitor.TryEnter,都将是唯一可以再次进入的线程。我不确定您是否按预期使用后台工作程序(BGW) 其背后的思想通常是,您不自己创建线程,而是向BGW指定要异步

请善良的灵魂解释一下为什么下面的psudocode不起作用。问题是,当从新线程调用时,无法在backgroundWorker(Monitor.TryEnter(bw))上获得锁。如果我从主UI线程调用它,它可以正常工作

谢谢 P


是否缺少监视器。请在if块末尾退出。
如果没有Monitor.Exit,则无论哪个线程首先成功执行Monitor.TryEnter,都将是唯一可以再次进入的线程。

我不确定您是否按预期使用后台工作程序(BGW)

其背后的思想通常是,您不自己创建线程,而是向BGW指定要异步完成的任务。因此,您的代码应该如下所示:

private BackgroundWorker bw = new BackgroundWorker ();
ctor 
{
    bw.DoWork += (sender, e) => DoStuff();
}

private void Button_Click(object sender, EventArgs e)
{
    bw.RunWorkerAsync();
}
有关详细信息,请参阅

评论:

  • 根据经验,永远不要锁定任意对象(就像您在bw上所做的那样),而是锁定唯一目的是锁定的对象。我建议你读乔恩·斯基特的优秀作品
  • 您可以通过设计器声明性地添加BGW,从而保存实例化和事件挂钩代码

  • bw对象是否实例化过?什么是//等。。。。等你能发布你的真实代码吗,也许这与这个伪代码不同?RunWorkerAsync尝试异步运行什么方法?bw是实例化的,当直接从UI线程调用DoSuff时工作正常。真正的代码是什么并不重要,因为永远不会到达代码,因为Monitor.TryEnter(bw)当从非UI线程调用DoStuff时,始终为false。这可能是一个+1的原因。我同意,但backgroundworker在应用程序中的行为就像一个消息泵,创建另一个线程的原因是释放UI线程,同时我预处理数据,然后将其发送给后台工作人员进行调度。不幸的是,我无法更改bw。我认为您可能会将BGW通知机制(实际上是基于消息泵)与异步调用混淆,后者简单地归结为BeginInvoke,它使用ThreadPool。我的观点是,您可以在BGW DoWork()函数中执行所有处理,它不会出现在UI ThreadThread上,谢谢,但上面的内容只是为了演示这个问题,我无法将BGW代码实际更改为现有应用程序的一部分,因此我必须按原样调用它,它工作正常。直到它没有从UI线程调用,不幸的是,UI线程在移交给BGW之前所做的处理太多,导致UI没有响应。我需要一种方法来下载UI线程,执行处理和调用BGW,但这是问题所在。然后考虑创建自己的BGW来运行现有代码(BGW内的BGW类型)。在Winforms中,大多数时候使用BGW比使用线程容易得多
    private BackgroundWorker bw = new BackgroundWorker ();
    ctor 
    {
        bw.DoWork += (sender, e) => DoStuff();
    }
    
    private void Button_Click(object sender, EventArgs e)
    {
        bw.RunWorkerAsync();
    }