【问题标题】:EventHandler doesn't fire after Thread re-creation线程重新创建后 EventHandler 不会触发
【发布时间】:2014-11-04 12:47:12
【问题描述】:

从 UI 线程,我使用后台工作程序创建另一个线程。在这个线程中 我正在使用 NetworkChanged 事件处理程序。一旦连接丢失,我 DoWorkEventArgs e.Cancel,关闭线程。 网络重新连接后,我使用相同的后台工作程序重新启动线程。 但是,从这一点开始,事件处理程序将不再因网络断开或重新连接而触发。

事件处理程序的代码位于使用初始后台工作程序启动的 Test 类中。

    public Test()
    {
        NetworkChange.NetworkAvailabilityChanged +=
            new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
    }

    protected virtual void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
    {
        try
        {
            if (e.IsAvailable)
            {
               IsConnectionActive = true;
               //recreate thread
            }
            else
            {
               IsConnectionActive = false;
               //Close thread
            }
        }
        catch
        {
        }
    }

我已经读到某些事件不是线程安全的,但我从其他示例中不明白我需要更改什么才能做到这一点。 (如果这甚至是问题) 我犯了什么错误,我该如何解决这个问题?

非常感谢。

编辑:

工作代码:

 private void backgroundWorker_DoWork(object sender,
        DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        worker.WorkerReportsProgress = true;
        worker.WorkerSupportsCancellation = true;

        RunModels(worker, e);       
    }

取消DoWork的代码:

    public void ModelsConnectionChanged(bool sender)
    {
        try
        {
            if (sender == false)
            {
                m_currentworker.ReportProgress(0, "DISCONNECT");
                m_currentworker.CancelAsync();
                DoWork.Cancel = true;
            }
        }
        catch (Exception e)
        {
            throw e;
        }
    }

【问题讨论】:

  • 您能发布(部分)DoWork(...) 代码吗?当你想取消后台工作时,你必须在你的DoWork处理程序中检查CancelationPending
  • 将代码添加到主要问题中。我将事件处理程序传递给我的类并将其重命名为 DoWork(我知道,命名约定不是最好的)。

标签: c# multithreading event-handling


【解决方案1】:

这些行:

worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;

必须在之前移动:

worker.RunWorkerAsync();

他们来错地方了。 此外,您不能在DoWork 处理程序中使用m_currentworker.CancelAsync();;必须从您要停止工作人员的位置调用它。此外,在您的 RunModels(worker, e); 中,您必须检查 worker.CancellationPending 并在此标志设置为 true 时停止。

实际发生的情况是,当您调用 CancelAsync(); 时,标志 CancellationPending 设置为 true。尽快从DoWork(...)返回是你的工作。

【讨论】:

  • 添加了您建议的更改,但这并没有改变问题。线程被取消。但是,当它重新启动时,事件处理程序仍然不会触发。
  • 至少没有线程混在一起了。您能否添加一些 Debug.WriteLine,看看幕后发生了什么?
猜你喜欢
  • 2010-12-18
  • 1970-01-01
  • 1970-01-01
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多