0

我正在运行一个正在发送邮件的线程。我怎么知道一个线程已经完成了它的执行?

new Thread(x => SendMail(node.Attributes["id"].Value.ToString(), node["fname"].InnerText +      " " + node["lname"].InnerText, 500, node["email"].InnerText)).Start();
4

5 回答 5

3
var thr = new Thread(x => SendMail(node.Attributes["id"].Value.ToString(), node["fname"].InnerText +      " " + node["lname"].InnerText, 500, node["email"].InnerText));
thr.Start();
thr.Join();//In this place main thread will wait
于 2013-01-11T13:09:48.227 回答
2

您应该保留对您创建的线程实例的引用,然后检查ThreadState. 您还可以检查该IsAlive属性以查看线程当前是否正在执行。

于 2013-01-11T13:07:13.770 回答
2

这取决于你的环境是什么。例如,您可以通过使用任务和订阅延续来避免所有线程。

例如

var task = Task.Run(DoSomething)
               .ContinueWith(a => Whatever())

或者使用 C# 5 提供的便利关键字:

var task = await Task.Run(DoSomething);
Whatever();

如果您必须使用线程,我建议您传递一个委托,当电子邮件完成后,您只需调用它:

// Outside the thread
private Action callback;

// Before starting the thread
callback = MyMethod/*Or a lambda if you want*/;

// In the thread action
Action<object> threadBody = x => 
{
    SendMail(node.Attributes["id"].Value.ToString(), node["fname"].InnerText +      " " + node["lname"].InnerText, 500, node["email"].InnerText);
    callback();
};
于 2013-01-11T13:13:17.560 回答
2

另一种变体是将 与ThreadPool.QueueUserWorkItem结合使用ManualResetEvent

如:

private void DoWork()
{
    List<ManualResetEvent> events = new List<ManualResetEvent>();

    //in case you need to loop through multiple email addresses 
    //use the foreach here, assuming that the items is a list.

    //foreach(var item in items)
    //{
    var resetEvent = new ManualResetEvent(false);
    ThreadPool.QueueUserWorkItem(arg =>
    {
        SendMail(node.Attributes["id"].Value.ToString(), 
           node["fname"].InnerText + " " + node["lname"].InnerText,
           500, node["email"].InnerText);
        resetEvent.Set();
    });
    events.Add(resetEvent);

    //} <- closes the foreach loop

    //WaitHandle.WaitAll waits for all the threads to finish.
    WaitHandle.WaitAll(events.ToArray());
    MessageBox.Show("Mails are sent", "Notification");
}

如果您想遍历电子邮件地址列表或数组并为每封邮件单独启动一个线程,这将特别有用。

在您的情况下,如果您想在等待发送邮件时做其他事情。您可以简单地在后台线程中运行上面的代码,当消息显示时,您就知道工作已完成。

public void StartMailThread()
{
    Thread myThread = new Thread(DoWork)
    {
        IsBackground = true,
        Name = "MailThread"
    };
    myThread.Start();
}

虽然,使用线程启动线程池对我来说似乎有点奇怪。

于 2013-01-11T13:20:11.837 回答
1

除了 Andrew's Answer 你可以使用 BackgroundWorker 它已经有 RunWorkerCompleted 事件 BackgroundWorker

于 2013-01-11T20:18:18.103 回答