【问题标题】:How to wait for a thread to finish execution in C#?如何在 C# 中等待线程完成执行?
【发布时间】:2012-11-05 23:10:52
【问题描述】:

我有一个快速连续调用的函数,它有一个打开的数据库连接。 我的问题是,在一个数据库连接关闭之前,该函数的另一个实例被调用,我可能会在数据库中收到死锁。

我试过了:

private static WaitHandle[] waitHandles = new WaitHandle[]
    {
        new AutoResetEvent(false)
    };

protected override void Broadcast(Data data, string updatedBy)
    {
        Action newAction = new Action(() =>
        {
        DataManagerFactory.PerformWithDataManager( 
            dataManager =>
            {
                // Update status and broadcast the changes
                data.UpdateModifiedColumns(dataManager, updatedBy);

                BroadcastManager.Instance().PerformBroadcast(
                    data,
                    BroadcastAction.Update,
                    Feature.None);
            },
            e => m_log.Error(ServerLog.ConfigIdlingRequestHandler_UpdateFailed() + e.Message));
            }
        );

        Thread workerThread = new Thread(new ThreadStart(newAction));
        ThreadPool.QueueUserWorkItem(workerThread.Start, waitHandles[0]);
        WaitHandle.WaitAll(waitHandles);
    }

但我收到一个线程错误并且程序冻结。我相信它与没有参数的线程启动函数有关。

感谢您的帮助

【问题讨论】:

  • QueueUserWorkItem中的第二个对象是参数。见MSDN
  • 通常你不会在ThreadPool 上排队一个新线程的Start 方法。这样就违背了目的。只需排队newAction。您可能应该锁定任何可能导致服务器端死锁的方法(PerformBroadcast?)。
  • ThreadPool.QueueUserWorkItem(newAction, null);不工作。 ThreadPool.QueueUserWorkItem(newAction, waitHandles[0]);不工作。

标签: c# multithreading concurrency waithandle


【解决方案1】:

这就是它的完成方式。创建完成这项工作的类:

public class MyAsyncClass
{

    public delegate void NotifyComplete(string message);
    public event NotifyComplete NotifyCompleteEvent;

    //Starts async thread...
    public void Start()
    {
        System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(DoSomeJob));
        t.Start();
    }

    void DoSomeJob()
    {
        //just wait 5 sec for nothing special...
        System.Threading.Thread.Sleep(5000);
        if (NotifyCompleteEvent != null)
        {
            NotifyCompleteEvent("My job is completed!");
        }
    }
}

现在这是另一个类的代码,它调用第一个:

 MyAsyncClass myClass = null;


    private void button2_Click(object sender, EventArgs e)
    {
        myClass = new MyAsyncClass();
        myClass.NotifyCompleteEvent += new MyAsyncClass.NotifyComplete(myClass_NotifyCompleteEvent);
        //here I start the job inside working class...
        myClass.Start();
    }

    //here my class is notified from working class when job is completed...
    delegate void myClassDelegate(string message);
    void myClass_NotifyCompleteEvent(string message)
    {
        if (this.InvokeRequired)
        {
            Delegate d = new myClassDelegate(myClass_NotifyCompleteEvent);
            this.Invoke(d, new object[] { message });
        }
        else
        {
            MessageBox.Show(message);
        }
    }

如果我需要解释一些细节,请告诉我。

替代方案是BackgroudWorker:

【讨论】:

  • 我只是等待线程结束。我不想有一个自定义类,我不想使用等待的 Action Fired 方法。有任何关于等待线程的提示吗?之后我不需要执行任何操作,我只需要停止父线程的执行,直到子线程完成,这样就没有更多的子线程可以执行所述代码。锁定代码块也不适用于公共静态只读变量
  • 最接近这个的是后台工作人员。但是你必须写几行。查看此链接了解更多详情:msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
  • 这也行不通,因为在我的操作中,我需要在事件 args 中没有可用的自定义数据
  • 据我了解您的情况,使用这些解决方案应该没有任何问题。如果应该在 UI 上等待,只需禁用表单上所需的部分。如果等待应该在代码中完成,请将私有参数放入您的类中。像 bool WorkingInProgress 之类的东西。作业开始时设置 WorkingInProgress=true。保持(使用 while)任何其他进程,直到 NotifyCompleteEvent 传递事件。然后设置 WorkingInProgress=false,并继续下一个线程。
猜你喜欢
  • 1970-01-01
  • 2014-03-18
  • 2021-08-10
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
  • 1970-01-01
  • 2012-07-07
相关资源
最近更新 更多