C# 我可以使用async和Task.Run使复杂方法异步吗?
我有一个复杂的方法,这个方法使webRequest,access数据库和其他工作C# 我可以使用async和Task.Run使复杂方法异步吗?,c#,asp.net,async-await,task,C#,Asp.net,Async Await,Task,我有一个复杂的方法,这个方法使webRequest,access数据库和其他工作 public string MyComplexMethod(params){ //Access db //Make WebRequests //... } 我通过以下方式使此方法异步: public async Task<string> MyComplexMethod(params) { //Access db //Make WebRequests //
public string MyComplexMethod(params){
//Access db
//Make WebRequests
//...
}
我通过以下方式使此方法异步:
public async Task<string> MyComplexMethod(params)
{
//Access db
//Make WebRequests
//...
}
public async Task MyComplexMethodAsync(params)
{
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);
}
public void OtherMethod()
{
//other stuff
MyComplexMethodAsync(params);
//other stuff
}
我可以使用异步的,主要是Task.Run这样复杂的方法吗?
或者有其他方法使此方法异步?由
任务包装。运行方法不需要异步
public string MyComplexMethod() {}
public Task MyComplexMethodAsync()
{
return Task.Run(() => MyComplexMethod());
}
但是使用上面的示例不要使您的方法像async wait
那样是异步的。
您提到,您的复杂方法使用Web服务和数据库查询,这使您的方法成为实现异步的最佳候选方法。
async await
主要用于有效地使用外部资源,而不使用额外的线程执行只等待响应而不执行任何操作的操作
只要您需要,它就会为每个“接触”外部资源的操作创建自己的异步方法,大多数“客户机”已经为使用数据库或web服务提供了异步方法
// Access Db
public async Task<object> GetValueFromDatabaseAsync()
{
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(query, connection))
{
await connection.OpenAsync();
return await command.ExecuteScalarAsync();
}
}
// Make web request
public async Task<HttpResponseMessage> SendRequestToWebServiceAsync(SomeData data)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(webserviceUrl);
return await client.PostAsJsonAsync("api/values", data);
}
}
被任务包装。Run
方法不需要是异步的
public string MyComplexMethod() {}
public Task MyComplexMethodAsync()
{
return Task.Run(() => MyComplexMethod());
}
但是使用上面的示例不要使您的方法像async wait
那样是异步的。
您提到,您的复杂方法使用Web服务和数据库查询,这使您的方法成为实现异步的最佳候选方法。
async await
主要用于有效地使用外部资源,而不使用额外的线程执行只等待响应而不执行任何操作的操作
只要您需要,它就会为每个“接触”外部资源的操作创建自己的异步方法,大多数“客户机”已经为使用数据库或web服务提供了异步方法
// Access Db
public async Task<object> GetValueFromDatabaseAsync()
{
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(query, connection))
{
await connection.OpenAsync();
return await command.ExecuteScalarAsync();
}
}
// Make web request
public async Task<HttpResponseMessage> SendRequestToWebServiceAsync(SomeData data)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(webserviceUrl);
return await client.PostAsJsonAsync("api/values", data);
}
}
我认为使用async/await是正确的
async告诉编译器,在到达wait关键字后,将使用该方法ContinueWith包装所有内容
public void Something()
{
var task = new Task(() => DoWork());
task.ContinueWith(() => MoreWorkAfter());
task.Start();
}
//Is the same as
public async void Something()
{
var task = new Task(() => DoWork());
task.Start();
await Task;
MoreWorkAfter();
}
//Is also the same as
public async void Something()
{
var task = Task.Run(() => DoWork());
await Task;
MoreWorkAfter();
}
//Still the same as
public async void Something()
{
await Task.Run(() => DoWork());
MoreWorkAfter();
}
要使方法本身可等待,它还必须返回一个Task对象,因为Task具有等待所寻找的GetAwaiter()。只要记住,如果你不开始这项任务,它将永远等着你。所以这里也有同样的方法,是以一种让其他人期待的方式编写的
public Task SomethingAsync()
{
return Task.Run(() => DoWork());
}
//Same as...
public async Task SomethingAsync()
{
await Task.Run(() => DoWork());
}
//And now in other methods you can....
public async void AnotherMethod()
{
await SomethingAsync();
//Do more work after it's complete.
}
需要注意的是,一旦任务启动,它就在一个新线程上运行,为了回答您的问题,是的,它卸载了工作。因此,对于原始方法,请保持不变。异步方法可以执行此任务。请像以前一样运行它
public string MyComplexMethod(params)
{
//Access db
//Make WebRequests
//...
}
public async Task MyComplexMethodAsync(params)
{
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);
}
然而,需要注意的是;尽管你可以打电话:
await MyComplexMethodAsync(params);
您已配置等待(false)
这意味着在该方法中,任务之后的任何代码都不会在当前上下文中
public async Task MyComplexMethodAsync(params)
{
//Main thread work here
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);//Background work here
//This will also be background work since CongfigureAwait(false);
}
public async Task MyComplexMethodAsync(params)
{
//Main thread work here
await Task.Run(() => MyComplexMethod()); //Background work here
//Main thread work here again since CongfigureAwait defaults to true;
}
我说主线程可以工作,但前提是主线程称为MyComplexMethodAsync
掌握它最简单的方法就是想象等待关键字之后的一切基本上都是一个新的动作,任务完成后会被调用;就像使用ContinueWith一样
如果方法中的await关键字后面有代码,那么它将被安排在主线程上运行(考虑到从哪个主线程开始调用该方法)。这意味着,如果您曾经使用过Dispatcher.BeginInvoke,它有点像使用Dispatcher.BeginInvoke。get的剩余部分排队以便更好地在主线程上运行。(同样,除非您将ConfigureAwait(false)设置为空,否则它不会设置)我认为您使用async/await的路径是正确的
async告诉编译器,在到达wait关键字后,将使用该方法ContinueWith包装所有内容
public void Something()
{
var task = new Task(() => DoWork());
task.ContinueWith(() => MoreWorkAfter());
task.Start();
}
//Is the same as
public async void Something()
{
var task = new Task(() => DoWork());
task.Start();
await Task;
MoreWorkAfter();
}
//Is also the same as
public async void Something()
{
var task = Task.Run(() => DoWork());
await Task;
MoreWorkAfter();
}
//Still the same as
public async void Something()
{
await Task.Run(() => DoWork());
MoreWorkAfter();
}
要使方法本身可等待,它还必须返回一个Task对象,因为Task具有等待所寻找的GetAwaiter()。只要记住,如果你不开始这项任务,它将永远等着你。所以这里也有同样的方法,是以一种让其他人期待的方式编写的
public Task SomethingAsync()
{
return Task.Run(() => DoWork());
}
//Same as...
public async Task SomethingAsync()
{
await Task.Run(() => DoWork());
}
//And now in other methods you can....
public async void AnotherMethod()
{
await SomethingAsync();
//Do more work after it's complete.
}
需要注意的是,一旦任务启动,它就在一个新线程上运行,为了回答您的问题,是的,它卸载了工作。因此,对于原始方法,请保持不变。异步方法可以执行此任务。请像以前一样运行它
public string MyComplexMethod(params)
{
//Access db
//Make WebRequests
//...
}
public async Task MyComplexMethodAsync(params)
{
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);
}
然而,需要注意的是;尽管你可以打电话:
await MyComplexMethodAsync(params);
您已配置等待(false)
这意味着在该方法中,任务之后的任何代码都不会在当前上下文中
public async Task MyComplexMethodAsync(params)
{
//Main thread work here
await Task.Run(() => MyComplexMethod()).ConfigureAwait(false);//Background work here
//This will also be background work since CongfigureAwait(false);
}
public async Task MyComplexMethodAsync(params)
{
//Main thread work here
await Task.Run(() => MyComplexMethod()); //Background work here
//Main thread work here again since CongfigureAwait defaults to true;
}
我说主线程可以工作,但前提是主线程称为MyComplexMethodAsync
掌握它最简单的方法就是想象等待关键字之后的一切基本上都是一个新的动作,任务完成后会被调用;就像使用ContinueWith一样
如果方法中的await关键字后面有代码,那么它将被安排在主线程上运行(考虑到从哪个主线程开始调用该方法)。这意味着,如果您曾经使用过Dispatcher.BeginInvoke,它有点像使用Dispatcher.BeginInvoke。get的剩余部分排队以便更好地在主线程上运行。(同样,除非您将ConfigureAwait(false)设置为空,否则它不会设置)非常感谢您的回答,您的回答打开了我对async/await的思路,我将更改代码。但只是为了澄清我的疑问,将那个复杂的方法放在Task.Run中是否“正确”?或者我必须使用Task.Run只使用更简单的方法吗?@BrunoCanto,禁止将异步方法放入Task.Run
是错误的方法。检查原因:非常感谢您,您的回答让我对async/Wait产生了兴趣,我将更改代码。但只是为了澄清我的疑问,将那个复杂的方法放在Task.Run中是否“正确”?或者我必须使用Task.Run只使用更简单的方法吗?@BrunoCanto,禁止将异步方法放入Task.Run
是错误的方法。检查原因:为什么要使用任务。在ASP.NET中运行?你已经在线程池中了,为什么还要更多线程