2017-02-06 58 views
0

カスタムイーサネットデバイスからデータを読み込むためのビジュアルスタジオ2015 c#プログラムを作成しました。データがスケジュールされた時間にすべて一緒に読み込まれるため、非同期命令を使用する必要があります。c#async await and exception

私は読取りデータ用にカスタム.NETライブラリを使用します。これは私のコードです:

private void timerPollingData_Tick(object sender, EventArgs e) 
{ 
    readDevice_01(); 
    readDevice_02(); 
    // and so on for all devices ... 
} 

private async void readDevice_01() 
{ 
    var result = await getDataDevice_01(); 
    // Save data 
} 

private async void readDevice_02() 
{ 
    var result = await getDataDevice_02(); 
    // Save data 
} 

private Task<string> getDataDevice_01() 
{ 
    MyCustomLibrary readDevice = new MyCustomLibrary.Master(); 
    return Task.Factory.StartNew(() => readDevice.ReadHoldingRegister(... some parameters ...).ToString());      
} 

private Task<string> getDataDevice_02() 
{ 
    MyCustomLibrary readDevice = new MyCustomLibrary.Master(); 
    return Task.Factory.StartNew(() => readDevice.ReadHoldingRegister(... some parameters ...).ToString());      
} 

私の疑問: 各タスクのハンドル例外のためのベストプラクティスは何ですか?どのデバイスがイーサネットから抜かれているのかを理解し、スイッチをオフにして、そこからデータを取得するために使用されたタスクを停止する必要があります。

ご協力いただきありがとうございます。

+5

* 'async void'を使用しないでください。これはイベントハンドラ専用です。それを待つことも、例外をキャッチすることもできません。何も返さない場合は 'async Task'を使います。 –

+0

@PanagiotisKanavos - TimerTickは優れた標準アドバイスですが、イベントハンドラです。したがって、2つの '非同期void'メソッドへの伝播は大きくはありませんが、どちらも間違っているわけではありません。 –

+0

どのVisual Studioを知る必要はありませんが、これがWindowsサービスかWinFormsアプリケーションかどうかを教えてください。 –

答えて

0

async voidを避ける必要があります。非同期イベントハンドラ以外のすべてにasync Taskを使用してください。詳細については、私の記事async best practicesを参照してください。

また、StartNewを使用しないでください。不適切なデフォルトのパラメータ値を持つ、低レベルで非常に危険なAPIです。 StartNewの代わりにTask.Runを使用してください。詳細については、StartNew is dangerousのブログ記事をご覧ください。

スケジュールされた時間にデータがすべて一緒に読み込まれるため、非同期待機命令を使用する必要があります。

非同期は、お使いのデバイスのAPIは、非同期メソッドを持っていない場合はTask.Runで使用できる同時実行の一形態では、次のとおりです。

private async void timerPollingData_Tick(object sender, EventArgs e) 
{ 
    var task1 = readDevice_01(); 
    var task2 = readDevice_02(); 
    // and so on for all devices ... 
    await Task.WhenAll(task1, task2, ...); 
} 

private async Task readDevice_01() 
{ 
    var result = await Task.Run(() => getDataDevice_01()); 
    // Save data 
} 

private string getDataDevice_01() 
{ 
    MyCustomLibrary readDevice = new MyCustomLibrary.Master(); 
    return readDevice.ReadHoldingRegister(... some parameters ...).ToString();      
} 

あなたのAPIがReadHoldingRegisterAsyncメソッドを持っていた場合、これは次のようになります

private async void timerPollingData_Tick(object sender, EventArgs e) 
{ 
    var task1 = readDevice_01Async(); 
    var task2 = readDevice_02Async(); 
    // and so on for all devices ... 
    await Task.WhenAll(task1, task2, ...); 
} 

private async Task readDevice_01Async() 
{ 
    var result = await getDataDevice_01Async(); 
    // Save data 
} 

private async Task<string> getDataDevice_01Async() 
{ 
    MyCustomLibrary readDevice = new MyCustomLibrary.Master(); 
    var result = await readDevice.ReadHoldingRegisterAsync(... some parameters ...); 
    return result.ToString(); 
} 

私の疑問を::より多くの自然のように表現するものです各タスクの例外処理のベストプラクティス?どのデバイスがイーサネットから抜かれているのかを理解し、スイッチをオフにして、そこからデータを取得するために使用されたタスクを停止する必要があります。

タスクからの例外を取得するためのベストプラクティスは、awaitです。

例外が発生した後にタスクを停止する心配はありません。タスクが例外を報告するまでに、タスクはすでに停止しています。

+0

こんにちはStephen、 サンプルコードはありがとうございます。私のカスタムライブラリ(またはAPI)がデータを読み取るための非同期メソッドを持っているか持っていないのか分かりません。だから、今私は最初のコードサンプルのように私のコードを変更しようとします。来週、私はいくつかのテストをすることを望みます。結果をこのディスカッションに更新してください ありがとう – jumpier