我听说在多线程方面的责任应该落在应用程序上,而在异步方法中不应使用Task.Run或者TaskFactory.StartNew。
然而,如果我有一个库提供了做相当重的计算的方法,那么为了释放一些正在接受asp .net core http请求的线程,我能否将这个方法变成异步并使其运行一个长时间运行的task?或者这应该是一个同步方法,而asp .net core应用程序应该负责启动任务呢?
我听说在多线程方面的责任应该落在应用程序上,而在异步方法中不应使用Task.Run或者TaskFactory.StartNew。
然而,如果我有一个库提供了做相当重的计算的方法,那么为了释放一些正在接受asp .net core http请求的线程,我能否将这个方法变成异步并使其运行一个长时间运行的task?或者这应该是一个同步方法,而asp .net core应用程序应该负责启动任务呢?
public Task SleepAsync(int millisecondsTimeout)
{
return Task.Run(() => Sleep(millisecondsTimeout));
}
还有另一种新的实现:
public Task SleepAsync(int millisecondsTimeout)
{
TaskCompletionSource<bool> tcs = null;
var t = new Timer(delegate { tcs.TrySetResult(true); }, null, –1, -1);
tcs = new TaskCompletionSource<bool>(t);
t.Change(millisecondsTimeout, -1);
return tcs.Task;
}
Task.Run
包装调用并不会暴露可扩展性,而是转移负载。但是,该库的用户并不知道这一点。您的库的用户可以自己使用 Task.Run
包装该调用。我真的认为他必须这样做。并不完全回答问题(我认为其他答案已经足够好了),但是要添加一些额外的建议:在库中使用Task.Run时要小心,因为它可能会导致库用户意想不到的线程池耗尽。例如,开发人员正在使用许多第三方库,它们都使用Task.Run()等。现在开发人员也尝试在他的应用程序中使用Task.Run,但它会减慢他的应用程序,因为线程池已经被第三方库使用完了。
当您想要使用Parallel.ForEach并行处理时,这是一个不同的问题。