2017-09-01 10 views
2

最初の質問を非同期されていない関数の内部で待つ: 私は非同期としてマークされていない関数の内部待つ使うことはできますか?非同期プログラミング:

詳細はこちら。私はこの投稿を読んでいました。 Hololens- Capturing Photo...あなたが見ることができるように、著者はいくつかのコードを投稿しました。その中で この

void Start() 
    { 
     getFolderPath(); 
     while (!haveFolderPath) 
     { 
      Debug.Log("Waiting for folder path..."); 
     } 
     Debug.Log("About to call CreateAsync"); 
     PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated); 
     Debug.Log("Called CreateAsync"); 
    } 


    async void getFolderPath() 
    { 
     StorageLibrary myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures); 
     Windows.Storage.StorageFolder savePicturesFolder = myPictures.SaveFolder; 
     Debug.Log("savePicturesFolder.Path is " + savePicturesFolder.Path); 
     folderPath = savePicturesFolder.Path; 
     haveFolderPath = true; 
    } 

は今getFolderPathは(イベントハンドラなど)voidを返すが、ドキュメントはこれらのメソッドを待つことができないと言っているかに気づきます。代わりに、whileループを使用することを著者が待っています。

しかし、私はこれを行う場合

 void Start() 
     { 
      await getFolderPath(); 

      Debug.Log("About to call CreateAsync"); 
      PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated); 
      Debug.Log("Called CreateAsync"); 
     } 


    //Notice how now it returns Task 
     async Task getFolderPath() 
     { 
      StorageLibrary myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures); 
//..... 
     } 

が、私はこれを行うことができますか?

答えて

2

人々がasyncawait背後に何があるか忘れがち。 asyncではありませんが、あなたが返さTaskContinueWithを呼び出し、タスクが完了したときにのみ実行される明示的な継続を提供することができる方法で

いいえ、あなたことができませんawait

class Example 
{ 
    public void Start() 
    { 
     getFolderPath() 
      .ContinueWith(t => 
      {     
       Console.WriteLine("..."); 
      }); 
    } 

    async Task getFolderPath() 
    { 
     await Task.Delay(1000); 
    } 
} 

同等だこと〜

class Example 
{ 
    public async Task Start() 
    { 
     await getFolderPath(); 
     Console.WriteLine("..."); 
    } 


    async Task getFolderPath() 
    { 
     await Task.Delay(1000); 
    } 
} 
+0

技術的には真ですが、 'ContinueWith'は低レベルの危険なAPIです。代わりに 'await'を使うことができます。 –

+0

@StephenCleary:「低レベル」だと私は同意しますが、私は "危険な"人に頭を向けます。それはちょうど意見ですか、あるいはいくつかの根拠がありますか? –

+1

[ここでは長い議論がある](https://blog.stephencleary.com/2015/01/a-tour-of-task-part-7-continuations.html)。要約すると、最も一般的な危険な部分は、非同期のデリゲートを理解できず、デフォルトでスレッドプールを使用しない(ほとんどの人が想定しているように)、 'CancellationToken'は実行中のデリゲートを取り消します。動的なタスクの並列処理を行う場合にのみ意味をなさない引数のデフォルト値もあります。非同期プログラミングではありません。特に、非同期プログラミングのために使用するときは常に* TaskSchedulerと* TaskContinuationOptionsを渡すべきです。 –

0

awaitファンクションコールのメソッド呼び出しには、asyncとマークすることはできません。したがって、2番目の例はコンパイルされません。しかし、Startメソッドをasyncとマークすることができます。

Async awaitは、機能の実行を待機する非ブロック方法です。この場合、実行はGetFolderPathメソッドで待たされますが、これが待機している間はStartメソッドの実行は続行されます。このため、著者はwhile loopを使用してgetFolderPathの実行が完了するのを待つと仮定します。

0

最初の質問に対する回答はです。いいえ、あなたはできません。公式documentation

awaitからのみasync キーワードによって変更非同期方式で使用することができます。 async修飾子を使用して定義されたこのようなメソッドと、通常は1つ以上の待機式を含む は、非同期メソッド と呼ばれます。

あなたはstartメソッドの内部で非同期メソッド getFolderPathの実行を待つしたい場合は、 async await文脈では

public async Task Start() 
{ 
    await getFolderPath(); 

    Debug.Log("About to call CreateAsync"); 
    PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated); 
    Debug.Log("Called CreateAsync"); 
} 

するシグネチャを更新する必要があり

、戻り値の型としてTask、手段タスクが同期アプローチでvoidに相当する値を返さないことを確認します。たとえば、非同期タスクからstringを返す必要がある場合は、public async Task<string> GetFoo()が必要です。

全体的に見ると、あなたが見ている例のコードでは、いくつかのレビューが必要だと思います。

+0

ありがとうございます。しかし、非同期ではなく、タスクではありませんか? (getFolderPathが上記のコードでTaskを返す方法に注目してください)私は、あなたが話している同等性を理解していると思うが、Startが非同期ではないとタスクを返す方法は? – KansaiRobot

+0

@KansaiRobot:実際には 'public async Task Start 。 –

+0

ありがとうございました。それを指摘してくれてありがとう、私はそれを追加するのを忘れました –

0

あなたが明示的に終了するGetFolderPath方法に待つことができる:

void Start() 
    { 
     getFolderPath().Wait(); 

     Debug.Log("About to call CreateAsync"); 
     PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated); 
     Debug.Log("Called CreateAsync"); 
    } 


//Notice how now it returns Task 
    async Task getFolderPath() 
    { 
     StorageLibrary myPictures = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Pictures); 
     //..... 
    } 

をしかし、その後、あなたがWait以来、同期1で非同期メソッドを回っているが、ブロッキング方式である(それが中に何が起こるかでありますwhileループはとにかく)。

あなたの目的は、操作を非同期に維持することであるならば、あなたはダニエルOrmeñoの提案に行かなければならない:

async Task Start() 
    { 
     await getFolderPath(); 

     Debug.Log("About to call CreateAsync"); 
     PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated); 
     Debug.Log("Called CreateAsync"); 
    } 
+0

これは、私が非同期プログラミングについて困惑していることです。つまり、呼び出された非同期関数と無関係にすることができたら、待機するだけです。これは同期的なものです。 – KansaiRobot

+1

いずれにしてもお待ちください。問題は、実行中のスレッドがブロックされているかどうかです。 非同期:コードは、待機が返るまで実行を停止しますが、スレッドは引き続き他のアクションを処理できます。 同期:スレッド全体が待機をブロックします。 これは、コードが実行されているスレッドがUIスレッドである場合に最も適しています。 asycnhronous呼び出しを使用すると、UIは応答し続けます。ブロックするのを待つと、UIはフリーズします。 –

+0

@ダニエル・オルメニョ:私の知っている通りです(私の答えに示されているように)。このテクニックは、非同期メソッドを使用する必要がある場合(たとえば、3番目のクラスのクラスライブラリで)、同期する必要のあるメソッドから変更できない(または保持したい)場合に便利です。 –

関連する問題