简体   繁体   English

如何在同步方法中调用异步方法?

[英]How can I call an async method within a sync method?

I'm trying to call an async task (SIn) within a synch method (SignIn). 我正在尝试在同步方法(SignIn)中调用异步任务(SIn)。 I need the synch method because I'm passing ref to that method. 我需要synch方法,因为我将ref传递给该方法。 But when I'm calling the async task, the GUI is frozen. 但是,当我调用异步任务时,GUI被冻结。 The async task is a simple login with the onedrive sdk. 异步任务是使用onedrive sdk的简单登录。

I've tried to waited the task, but the GUI still frozen. 我试图等待任务,但GUI仍然冻结。 I've also tried creating a new Thread, but it didn't work too. 我也尝试过创建新的线程,但是它也没有用。 How can I call the async method? 如何调用异步方法?

public override bool SignIn(ref User user)
{
   try
   {
      signInEnd = false;
      signinUser = user;

      Task<bool> task = SIn();
      task.Wait();

      return task.Result;
   }
   catch(Exception e)
   {
      return false;
   }
}

public async Task<bool> SIn()
{
   var msaAuthProvider = new MsaAuthenticationProvider(
          this.oneDriveClientId,
          this.oneDriveReturnUrl,
          this.scopes,
          new CredentialVault(this.oneDriveClientId));
   await msaAuthProvider.AuthenticateUserAsync();
   driveClient = new OneDriveClient(this.oneDriveBaseUrl, msaAuthProvider);
}

Calling Wait() blocks the UI thread which means that the continuation of SIn() , ie the part that will eventually be executed once the Task returned by AuthenticateUserAsync() has completed, won't be able to execute on this thread. 调用Wait()阻止UI线程,这意味着SIn()的继续SIn()AuthenticateUserAsync()返回的Task完成后最终将要执行的部分AuthenticateUserAsync()将无法在此线程上执行。 This results in a deadlock. 这将导致死锁。

You may be able to get around this by avoiding capturing the context by calling ConfigureAwait(false) in SIn() : 您可以通过在SIn()调用ConfigureAwait(false)来避免捕获上下文,从而解决此问题:

public async Task<bool> SIn()
{
    var msaAuthProvider = new MsaAuthenticationProvider(
           this.oneDriveClientId,
           this.oneDriveReturnUrl,
           this.scopes,
           new CredentialVault(this.oneDriveClientId));
    await msaAuthProvider.AuthenticateUserAsync().ConfigureAwait(false);
    driveClient = new OneDriveClient(this.oneDriveBaseUrl, msaAuthProvider);
}

But the "real" solution to this kind of issues is not to mix asynchronous and synchronous code, ie SignIn should be asynchronous and await SIn() . 但是,针对此类问题的“真正”解决方案不是混合使用异步代码和同步代码,即SignIn应该是异步的并等待SIn() Don't block on asynchronous code by calling Wait() or Result : 不要通过调用Wait()Result阻塞异步代码:

public Task<bool> SignIn(User user)
{
    try
    {
        ...
        return await SIn();
    }
    catch (Exception e)
    {
        return false;
    }
}

Please refer to @Stephen Cleary's blog post for more information about this. 请参阅@Stephen Cleary的博客文章 ,以获取有关此信息的更多信息。

mm8 is right that not calling async from inside a sync method is the best way to solve your issue, mm8是对的,不要从sync方法内部调用async是解决问题的最佳方法,

remember that the public async void EventHandler() method was specifically designed for running long running tasks from a gui linked control 请记住, public async void EventHandler()方法是专门为从gui链接控件中运行长时间运行的任务而设计的

However it isn't always possible to rewrite an entire system to be async when only one small section needs changing 但是,当仅需要更改一小部分时,并非总是可能将整个系统重写为异步的

In this case you should avoid waiting for the results as this makes the async process pointless, what you can do though is break your synchronous code into 2 parts a before and after 在这种情况下,您应该避免等待结果,因为这会使异步过程变得毫无意义,但是您可以做的是将同步代码分为前后两部分

  • the before method will prep and launch the task, before方法将准备并启动任务,
  • the after handles the results 事后处理结果

ie

public async Task<string> GetData(int delay)
{
    await Task.Delay(delay);
    return "complete";
}

public void StartGettingData()
{
    GetData(5000).ContinueWith(t => CompleteGetData(t.Result), TaskScheduler.Current);
}

public void CompleteGetData(string message)
{
    UpdateStatus(message);
}

this method does have the added complexity of requiring you to ensure thread safety yourself, which is why the async/await functionality was introduced 此方法的确增加了复杂性,要​​求您自己确保线程安全,这就是引入异步/等待功能的原因

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM