2016-05-13 24 views
6

タスクが完了していても戻ってこないという問題があります。私は別のサーバー上にWebサイトとWebサービスを持っています。 Webサイトは、関数myFunction()を持つライブラリを利用するWebサービスを呼び出します。 Webサービスのサーバー上のコンソールアプリケーションからmyFunctionを呼び出すと、期待どおりに戻ります。ただし、WebサービスからmyFunction()を呼び出すためにWebサービスから呼び出しを行うと、 "Step 3"にはなりますが、 "Step 4"にはなりません。私は以下の呼び出しの簡略化されたバージョンを持っています。タスクを待つ完了後に戻ってこない

private string myFunction() 
{ 
    string myStr = myDoWork().GetAwaiter().GetResult(); 

    return myStr; 
} 

private async Task<string> myDoWork() 
{ 
    logger.Debug("Step 1"); 
    string answer = await aFunction(); 

    logger.Debug("Step 4"); 

    return answer; 
} 

public async Task<string> aFunction() 
{ 
    logger.Debug("Step 2"); 
    return await bFunction(CancellationToken.None); 
} 

AsyncLock myLock = new AsyncLock(); 
public Task<string> bFunction(CancellationToken cToken) 
{ 
    return Task.Run(
     async() => 
     { 
      using (await myLock(cToken)) 
      { 
       logger.Debug("Step 3"); 
       result = "Hello"; 
       return result; 
      } 
     }, 
     cToken); 
} 

私はasyncとawaitを初めて使用しているので、助けてください。

+0

可能であれば、 'myFunction()'もasyncでなければなりません。非同期呼び出しをブロックすると奇妙なことが起こります。また、なぜ 'Task.Run'ビジネスが' bFunction'にあるのですか? –

+0

「ステップ4」がここで実行されない理由はありません – Jonesopolis

+0

@NateBarbettiniなぜTask.Runのものなのか分かりません。私はできるだけコードを単純化しようとしましたが、重要な部分に注意を向けました。私は、同期タスクのために非同期であるように書かれたコードを再利用しています。非同期のものを使わずにそれをすべて書き直すことは、かなりの仕事です。 –

答えて

5

myFunction()ではほぼ確実にデッドロックです。ステップ4はメインスレッドで実行するようにスケジュールされていますが、メインスレッドがブロックされているために待機することはできません。GetResult()一般的に

private string myFunction() 
{ 
    string myStr = Task.Run(async() => await myDoWork()).Result; 

    return myStr; 
} 

private async Task<string> myDoWork() 
{ 
    logger.Debug("Step 1"); 
    string answer = await aFunction(); 

    logger.Debug("Step 4"); 

    return answer; 
} 

public async Task<string> aFunction() 
{ 
    logger.Debug("Step 2"); 
    return await bFunction(CancellationToken.None); 
} 

AsyncLock myLock = new AsyncLock(); 
public async Task<string> bFunction(CancellationToken cToken) 
{ 
    using (await myLock(cToken)) 
    { 
     logger.Debug("Step 3"); 
     result = "Hello"; 
     return result; 
    } 
} 

Task.Run() should be called可能な最高レベルから:

それはこれに近いものになるはずです。できるだけ同期させて、発信者がバックグラウンドスレッドを使用するかどうかを決定させます。

+0

ありがとうございました!これで修正されました。 –

+2

@ JesseMcConahieもっと良い解決策は 'myFunction'を非同期にし、' Task.Run'や '.GetResult()'を使わないようにコードを修正することです。 –

+0

@ScottChamberlain私は同意します。 –

関連する問題