2

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

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

任何可以提供帮助的示例或链接将不胜感激。

4

4 回答 4

2

为了总结这些选项,我将尝试在此处列出它们(也许将其设为社区 wiki 是个好主意)。

首先,您可以简单地在另一个线程中启动一个函数:

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一个代表

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来确保始终创建新线程)。在某些情况下(当您等待任务时)它甚至可以在同一个线程上执行,但它已经过优化,因此您不必担心。

这可能是在简单性与控制之间取得最佳折衷的选择(当然,没有真正的“最佳”)。以下是好处(从乔恩斯基特的回答中无耻地窃取):

  • 添加延续 (Task.ContinueWith)
  • 等待多个任务完成(全部或任何)
  • 捕获任务中的错误并在以后询问它们
  • 捕获取消(并允许您指定取消开始)
  • 可能有返回值
  • 在 C# 5 中使用等待
  • 更好地控制调度(如果要长时间运行,请在创建任务时说明,以便任务调度程序可以考虑到这一点)
于 2013-05-02T07:36:37.300 回答
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)应该是您想要在后台运行的任何内容。但是需要遵循这种参数形式,还有大量与 backgroundworker 相关的辅助函数,例如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

于 2013-05-02T07:07:37.073 回答
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!"; 
            }));
    });
于 2013-05-02T07:31:22.217 回答
0

我有一篇博文比较和对比了后台任务的各种实现,每个都有优点和缺点。剧透:Task绝对是最好的选择。另外,我推荐Task.Runover TaskFactory.StartNew

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

于 2013-05-02T11:36:10.760 回答