C# 如何在不等待异步方法完成的情况下启动它?

C# 如何在不等待异步方法完成的情况下启动它?,c#,asynchronous,C#,Asynchronous,有时我需要启动一个工作非常慢的异步作业。我不在乎那份工作是否成功,我需要继续我目前的工作 就像有时我需要发送一封电子邮件或短信,这是非常缓慢的工作。我需要尽快响应web客户端,这样我就不想等待它了 我在谷歌上搜索了这个问题,一些文章建议我这样写: // This method has to be async public async Task<Response> SomeHTTPAction() { // Some logic... // ... // Se

有时我需要启动一个工作非常慢的异步作业。我不在乎那份工作是否成功,我需要继续我目前的工作

就像有时我需要发送一封电子邮件或短信,这是非常缓慢的工作。我需要尽快响应web客户端,这样我就不想等待它了

我在谷歌上搜索了这个问题,一些文章建议我这样写:

// 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()检索值。这将创建一个新线程并在该新线程上运行方法,这相当昂贵/消耗资源。不是相关问题的答案。这个答案是正确的。我之所以投反对票,只是因为它与马文先生的一篇文章非常相似。