在.Net 4.5中使用async/await编写多线程方法
在.Net 4.5中使用async/await编写多线程方法
我有一个小问题。\n我承认在.Net 4.5之前,我并没有多次使用多线程,但是有了新的async/await
功能后,我决定尝试一下。我开始进行实验,一切看起来都还好,但是我找不到任何关于我的“问题”的解决方案。\n所以每个人都解释了如何在新的.Net平台的转换方法(例如WriteAsync()
,ReadAsync()
等)中使用await
,但是如果我想将其用于我自己的方法怎么办?例如,假设我正在执行一项非常昂贵的计算,并希望我的4个核心都能处理它。我可能会有类似于以下的代码:\n
async Task DoLotsOfWork(T[] data, int start, int end) { //执行非常昂贵的操作 }
\n但是由于我没有在那里使用await
关键字,该方法只被视为同步方法。我想在外部调用它4次,以便它可以在所有核心上运行,同时向用户显示一些合理的内容(例如“请稍等...”)。我能想到的唯一解决方案是在方法的开头添加await Task.Yield();
。就像这样:\n
async Task DoLotsOfWork(T[] data, int start, int end) { await Task.Yield(); //执行非常昂贵的操作 }
\n在这种情况下,方法的行为符合我的预期。但是是否有更好的解决方案?我觉得应该有比写那行代码更简单/更合理的方法。我知道我可以创建一个Task/Thread
对象并调用Start()
方法,但这需要更多的工作。我只是认为使用新的async/await功能应该更容易处理这种情况。
在使用.Net 4.5中编写多线程方法时,我们可能会遇到一些问题。下面是这个问题出现的原因以及解决方法:
问题的原因:
在这个例子中,我们需要执行一些非常昂贵的工作,但这个工作是同步的。这意味着当我们调用这个方法时,程序会一直阻塞,直到工作完成。这样会导致程序在执行这个工作时变得非常慢。
解决方法:
为了解决这个问题,我们可以使用异步/等待(async/await)关键字来实现多线程编程。下面是具体的解决方法:
首先,我们需要定义一个同步执行非常昂贵工作的方法:
public void DoLotsOfWork(T[] data, int start, int end) { Thread.Sleep(5000);//placeholder for real work }
然后,我们可以使用`Task.Run`方法在线程池线程中启动多个实例来执行这个工作:
Listtasks = new List (); for(int i = 0; i < 4; i++) { tasks.Add(Task.Run(() => DoLotsOfWork(data, start, end)); }
接下来,我们可以使用`Task.WhenAll`方法进行非阻塞等待,直到所有工作都完成:
await Task.WhenAll(tasks);
另外,我们还可以使用`Parallel`类来进行并行处理。这个类专门设计用于并行处理,可以自动将工作分割成多个任务,以充分利用可用的处理器核心。但是,这些并行方法会阻塞线程,直到所有任务都完成。所以,如果我们当前处于UI上下文中,不能阻塞线程直到任务完成,我们可以将这些方法包装在`Task.Run`中,以获得一个表示并行工作的`Task`。
// 使用Parallel类进行并行处理 Task.Run(() => { Parallel.For(0, 10, i => { // 执行并行工作 }); });
如果我们的一个任务返回一个值,我们可以使用`List
List> tasks = new List >(); for(int i = 0; i < 4; i++) { tasks.Add(Task.Run(() => myFunction())); } T[] results = await Task.WhenAll(tasks);
通过使用异步/等待关键字和任务并行处理,我们可以提高程序的性能和响应能力,使得程序能够更好地利用多核处理器的能力。