异步线程

时间:2013-05-02 07:01:38

标签: c# wpf multithreading

我想知道在哪里可以获得多线程或异步线程的示例。

在我忙的应用程序中,我必须在应用程序的后台运行一个线程来获取正在改变的值。每当这个值达到一定数量时,它就需要调用另一个函数。所有这些都必须在程序的后台运行,以便用户仍然可以在应用程序上执行其他操作。

任何可以提供帮助的示例或链接都会非常感激。

4 个答案:

答案 0 :(得分:2)

为了总结这些选项,我将尝试在这里列出它们(也许将它作为一个社区维基是个好主意。)

首先,您只需在另一个thread中启动一个函数:

Thread t = new Thread( ThreadProc );
t.Start();
// now you can wait for thread to finish with t.Join() or just continue
// Thread.IsBackground allows to control how thread lifetime influences
// the lifetime of the application

...
static void ThreadProc() {...} // can also be non-static, but for simplicity....

然后您可以使用BackgroundWorker

BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.DoWork += MyFunction;
bgWorker.RunWorkerAsync();

voud MyFunction(object o, DoWorkEventArgs args) {...}

您可以使用ProgressChangedRunWorkerCompleted事件进行更多控制(以及WorkerReportsProgress和其他属性)

另一种选择是使用ThreadPool,如果您的方法不会占用太多时间:

ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
...
static void ThreadProc(Object stateInfo) { ... }

另一种选择是致电BeginInvoke on a delegate

public delegate int MyDelegate(...);

MyDelegate del = SomeFunction;                     
IAsyncResult ar = del.BeginInvoke(...);
int result = del.EndInvoke(ar);

这将在线程池的线程上执行。如果你需要等待调用线程,你可以使用IAsyncResult.IsCompleted,但它会阻塞调用线程。

当然,您可以使用Task

var task = Task.Factory.StartNew(() => MyMethod());

这也会在线程池的线程上执行MyMethod,因此会应用相同的警告(尽管您可以使用TaskCreationOptions.LongRunning来确保始终创建新线程)。在某些情况下(等待任务时)它甚至可以在同一个线程上执行,但它已经过优化,所以你不必担心。

这可能是简单与控制之间最佳权衡的选择(当然,没有真正'最好的')。这些好处(从Jon Skeet's answer无耻地被盗):

  • 添加延续(Task.ContinueWith)
  • 等待完成多项任务(全部或全部)
  • 捕获任务中的错误并稍后查询
  • 捕获取消(并允许您指定取消开始)
  • 可能具有返回值
  • 在C#5中使用await
  • 更好地控制调度(如果它将长时间运行,请在创建任务时这样说,以便任务调度程序可以考虑到这一点)

答案 1 :(得分:1)

根据您所寻求的控制级别,BackgroundWorker可以很容易地在System.ComponentModel.BackgroundWorker内找到它。现在,这里有关于主题的MSDN文档的链接:http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

一个简单的用例场景就像这样:

BackgrouWorker BG = new BackgroudWorker();
GB.DoWork += YourFunctionDelegate(object Sender, EventArgs e);
GB.RunWorkerAsync();

现在YourFunctionDelegate(object Sender,EventArgs e)应该是您希望在后台运行的内容。但是需要遵循这个参数形式,还有很多与背景工作者相关的帮助函数,比如onProgressChanged事件,它允许监视明显的进度,如果你是线程的新手,可以证明是一开始就很痛苦如果你试图制作自己的主题。

如果您希望更多地控制执行以及线程如何运行,您应该在这里查看Task-Parallel-Library:http://msdn.microsoft.com/en-us/library/dd460717.aspx其中包含大量有关多线程的信息。

此处还有一个关于如何创建C#线程的精彩教程:http://support.microsoft.com/default.aspx?scid=kb;en-us;815804

答案 2 :(得分:1)

有关.Net 4.5中Windows 8上异步编程的概述:

http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx

对于.Net 4.0及更早版本,您可以使用ThreadPool

    System.Threading.ThreadPool.QueueUserWorkItem(obj =>
    {
        // Do some work
        for (int i = 0; i < 1000; i++)
            Math.Sin(i);

        // Get back to the UI thread
        App.Current.MainWindow.Dispatcher.BeginInvoke(
            new Action(delegate 
            { 
                block.Text = "Done!"; 
            }));
    });

答案 3 :(得分:0)

我有一篇compares and contrasts various implementations of background tasks的博文,各有优缺点。剧透:Task绝对是最好的选择。另外,我建议Task.Run超过TaskFactory.StartNew

如果您的后台操作是真正异步的,那么您可能根本不需要任何背景线程。 LINQPad有set of async examples这是一个很好的起点。这些是比其他人推荐的线程章节(由同一作者)更新的。

相关问题