【发布时间】:2014-12-19 00:10:47
【问题描述】:
我需要一个函数 A 来启动一个运行时间较长的异步方法函数 B(包括 Web 服务调用)。
即使函数 B 尚未返回,函数 A 也应该返回。
函数 B 不返回任何数据,即使它调用的函数 A 返回了也应该执行
使用 .Net 4.5 C#,最好的代码是什么,你能预见任何线程问题吗?
.net 上有很多示例,但要找到目的代码并不是那么简单。
【问题讨论】:
标签: .net multithreading asynchronous
我需要一个函数 A 来启动一个运行时间较长的异步方法函数 B(包括 Web 服务调用)。
即使函数 B 尚未返回,函数 A 也应该返回。
函数 B 不返回任何数据,即使它调用的函数 A 返回了也应该执行
使用 .Net 4.5 C#,最好的代码是什么,你能预见任何线程问题吗?
.net 上有很多示例,但要找到目的代码并不是那么简单。
【问题讨论】:
标签: .net multithreading asynchronous
即使函数 B 尚未返回,函数 A 也应该返回。
在这种情况下,关键是您不应该在await 上调用B。
启动一个运行时间较长的异步方法函数 B(包括 Web 服务调用)。
一般来说,如果大部分操作是 Web 服务调用,您应该不使用Task.Run。 Task.Run 将在后台线程上执行工作,这可能不是必需的,因为您可以使用异步 IO。
相反,创建一个async Task B() 方法,在方法中使用正常的await 机制,然后调用它。默认情况下,这会导致编译器警告,但您可以通过创建一个记录发生的异常的FireAndForget 扩展方法来解决此问题。
这可以很简单:
public static async void FireAndForget(this Task task)
{
try
{
await task;
}
catch (Exception e)
{
// Log the exception
}
}
这还提供了B() 中发生的日志记录问题的好处。
【讨论】:
Task.Run 而不是new Task - 你不需要调用 start
最简单的方法是使用Task.Run,它在一个新线程上执行一个动作:
public void A()
{
// Do something...
Task.Run(B);
// or, if you need to pass arguments to B:
// Task.Run(() => B(x, y, z));
// Do something else...
}
public void B()
{
// Do something...
}
注意不要让 B 抛出任何异常,否则会导致进程崩溃。
【讨论】:
Task.Run 立即返回,而 B 继续在单独的线程上运行。