C# 如何在不等待异步方法完成的情况下启动它?
有时我需要启动一个工作非常慢的异步作业。我不在乎那份工作是否成功,我需要继续我目前的工作 就像有时我需要发送一封电子邮件或短信,这是非常缓慢的工作。我需要尽快响应web客户端,这样我就不想等待它了 我在谷歌上搜索了这个问题,一些文章建议我这样写:C# 如何在不等待异步方法完成的情况下启动它?,c#,asynchronous,C#,Asynchronous,有时我需要启动一个工作非常慢的异步作业。我不在乎那份工作是否成功,我需要继续我目前的工作 就像有时我需要发送一封电子邮件或短信,这是非常缓慢的工作。我需要尽快响应web客户端,这样我就不想等待它了 我在谷歌上搜索了这个问题,一些文章建议我这样写: // This method has to be async public async Task<Response> SomeHTTPAction() { // Some logic... // ... // Se
// This method has to be async
public async Task<Response> SomeHTTPAction()
{
// Some logic...
// ...
// Send an Email but don't care if it successfully sent.
Task.Run(() => _emailService.SendEmailAsync());
return MyRespond();
}
// This method has to be async
public async Task<Response> SomeHTTPAction()
{
// Some logic...
// ...
// Send an Email but don't care if it successfully sent.
Task.Factory.StartNew(() => _emailService.SendEmailAsync());
return MyRespond();
}
//此方法必须是异步的
公共异步任务SomeHTTPAction()
{
//一些逻辑。。。
// ...
//发送电子邮件,但不在乎是否成功发送。
Task.Run(()=>\u emailService.sendmailasync());
返回MyRespond();
}
或者像这样:
// This method has to be async
public async Task<Response> SomeHTTPAction()
{
// Some logic...
// ...
// Send an Email but don't care if it successfully sent.
Task.Run(() => _emailService.SendEmailAsync());
return MyRespond();
}
// This method has to be async
public async Task<Response> SomeHTTPAction()
{
// Some logic...
// ...
// Send an Email but don't care if it successfully sent.
Task.Factory.StartNew(() => _emailService.SendEmailAsync());
return MyRespond();
}
//此方法必须是异步的
公共异步任务SomeHTTPAction()
{
//一些逻辑。。。
// ...
//发送电子邮件,但不在乎是否成功发送。
Task.Factory.StartNew(()=>\u emailService.sendmailasync());
返回MyRespond();
}
在呼叫完成之前,将出现一条警告:。考虑将“Acess”运算符应用到调用的结果。< /代码>
那么,如果我真的等待它呢?C#中的最佳实践是“触发并忘记”,只调用异步方法而不等待其完成 这完全取决于异步方法接受什么。通常,它将接受一个“特殊”类,该类也包含一个事件。您可以订阅该事件的回调方法,并将其与该方法一起传递。完成后,将调用回调方法
这方面的一个例子(对于插座)是:
public void CreateSocket()
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs sockAsync = new SocketAsyncEventArgs();
sockAsync.Completed += SockAsync_Completed;
s.ConnectAsync(sockAsync);
}
private void SockAsync_Completed(object sender, SocketAsyncEventArgs e)
{
//Do stuff with your callback object.
}
这完全取决于您尝试调用的方法可以接受什么。我会查看文档以获得更多帮助。正如Amadan在评论中所说的,您需要从函数中删除async。然后它会停止给你警告
// This method has to be async
public Response SomeHTTPAction()
{
// Some logic...
// ...
// Send an Email but don't care if it successfully sent.
Task.Factory.StartNew(() => _emailService.SendEmailAsync());
return MyRespond();
}
和Task.Factory.StartNew(()=>\u emailService.sendmailasync())
确实可以在一个新的线程上工作。如果你真的只是想启动并忘记。简单地说,不要调用useawait
// It is a good idea to add CancellationTokens
var asyncProcedure = SomeHTTPAction(cancellationToken).ConfigureAwait(false);
// Or If not simply do:
var asyncProcedure = SomeHTTPAction().ConfigureAwait(false);
如果您想在以后使用结果输出,它会变得更加棘手。但如果真的是火,忘记了上面的应该是有效的
取消令牌允许中断和取消过程。如果您使用的是取消令牌,那么您将需要在任何地方使用它,从检索到调用方法(一直到海龟)
我使用ConfigureAwait(false)
来防止死锁。想了解更多信息,我很好奇为什么没有人建议这样做
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
//what ever code here...e.g.
DoSomething();
UpdateSomething();
}).Start();
它只触发一个单独的线程。如果需要在函数中使用async
,也可以使用discard变量,而不使用wait。如果您有多个异步函数调用,但不需要等待所有调用,这也很有用
public async function(){
var tmp = await asyncfunction();
...
_ = _httpClient.PutAsync(url, content);
...
}
独立丢弃是避免此警告的最佳方法
_ = Task.Run(() => _emailService.SendEmailAsync());
丢弃是伪变量,可用于忽略异步操作返回的任务对象
只是不要将函数标记为异步,因此函数不应期望等待其结果?更好方法的可能重复是让这些操作在进程之外运行,即发布到rabbitmq之类的队列,让订阅者接收这些消息,然后发送电子邮件/SMW到目前为止您发现了哪些信息?在谷歌上快速搜索“C#async fire and forget”可以发现有很多资源可用于此……这真的不是设计问题吗?在你知道操作是否完成之前返回MyRespond
有什么意义?@MickyD主要是因为OP是如何完成的,但是有了它,你可以在以后使用.GetAwaiter().GetResult()检索值。这将创建一个新线程并在该新线程上运行方法,这相当昂贵/消耗资源。不是相关问题的答案。这个答案是正确的。我之所以投反对票,只是因为它与马文先生的一篇文章非常相似。