C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: 非同期処理の考え方


(過去ログ 162 を表示中)

[トピック内 10 記事 (1 - 10 表示)]  << 0 >>

■93848 / inTopicNo.1)  非同期処理の考え方
  
□投稿者/ ダージリン (1回)-(2020/02/12(Wed) 09:25:40)

分類:[.NET 全般] 

非同期処理の考え方についてです。

async/awaitができたおかげで、
GUIを含む処理であっても、同期処理風に簡単に処理の非同期処理化が
できるようになりました。
(例)
  private async void Func()
  {
      await Task.Run(() =>
      {
          非同期処理();
      });
      非同期処理の結果をGUI表示();
  }
でも、この場合のawaitって、あくまで正常系処理の終了待機に思えます。

たとえば、
非同期処理();の中で例外が起きる可能性があって、
例外処理の中で警告画面を表示するなど、GUIがらみの作業が必要になると、
昔通り、
  App.Current.Dispatcher.Invoke(() =>
  {
      GUI表示();
  });
としてます。

例外処理なだけに、awaitで待つわけにもいかず、
こういう場合は、昔通りの書き方しかないんでしょうか?

引用返信 編集キー/
■93849 / inTopicNo.2)  Re[1]: 非同期処理の考え方
□投稿者/ WebSurfer (2022回)-(2020/02/12(Wed) 09:38:39)
No93848 (ダージリン さん) に返信

> 例外処理なだけに、awaitで待つわけにもいかず、
> こういう場合は、昔通りの書き方しかないんでしょうか?

質問者さんの言う「例外」がどういうものによるかですが、それが予測できない
もしくは予測はできても何の対応もできない例外(例えば DB サーバーダウン)
が発生した場合は、ユーザーがそのまま作業を続けて事態を悪化させないために
も、例外をランタイムに拾わせてアプリケーションを停止させるべきです。

ユーザーへの通知が必要なら集約的例外処置という手段を取るべきと思います。
具体的には以下の記事を見てください。

デリゲートを利用した非同期メソッドの実装
http://surferonwww.info/BlogEngine/post/2019/06/19/coding-asynchronous-method-by-using-delegate-in-windows-forms-application.aspx


例外処理に関する詳しい話は以下の記事に書いてありますので一読されることを
お勧めします。

NETの例外処理 Part.1
https://blogs.msdn.microsoft.com/nakama/2008/12/29/net-part-1/

.NETの例外処理 Part.2
https://blogs.msdn.microsoft.com/nakama/2009/01/02/net-part-2/

記事の内容を簡単にまとめると:

(1) 予測可能で正しい業務フローに戻すことができる「業務エラー」(例:ユー
  ザーの入力間違い)と、予測できないもしくは予測はできても何の対応も
  できない「例外」(例:DB サーバーダウン)を区別して対処。

(2) 「例外」はランタイムに拾わせてアプリケーションを停止させる。

(3) よほどのことがない限り try-catch は書かない。

(4) キャッチせざるを得ない場合でも Execption はキャッチしない。(範囲を
  絞る。例えば DB 関係の例外で予測される SqlException に限定して catch
  するとか)

(5) 間違って補足してしまった例外は throw する。例えば SqlException に含
  まれる PK 制約違反だけは「業務エラー」として処置したいが、その他が原因
  で発生した SqlException を catch してしまった場合。(注:catch ブロック
  でキャッチした例外を throw するとスタックトレースが途切れるので単に
  throw と書く)

(6) ユーザーへの通知が必要なら集約的例外処置を利用する。

あと、.NET 4 からは破損状態例外は catch できなくなっているそうですが、「それ
でも Catch (Exception e) を使用するのはよくない」ということについては以下の
記事を見てください。

破損状態例外を処理する
https://docs.microsoft.com/ja-jp/archive/msdn-magazine/2009/february/clr-inside-out-handling-corrupted-state-exceptions

引用返信 編集キー/
■93850 / inTopicNo.3)  Re[1]: 非同期処理の考え方
□投稿者/ Hongliang (958回)-(2020/02/12(Wed) 09:41:00)
async/awaitが搭載された最初のC#だとできなかったような気もしないでもないですが、現在のC#では
try {
await DoWorkAsync();
}
catch (...) {
...
}
と記述できます。
UIスレッドでawaitしたのであれば、catch節もUIスレッドで実行されます。
引用返信 編集キー/
■93853 / inTopicNo.4)  Re[1]: 非同期処理の考え方
□投稿者/ WebSurfer (2024回)-(2020/02/12(Wed) 10:08:34)
No93848 (ダージリン さん) に返信

【追伸】

上の私のレスの (4), (5) に書いたことをするため例外を catch する場合は
普通に try - catch 文を書けばいいはずです。

具体例は、先に紹介した記事(URL 再掲します)の最初の方のサンプルコード
に「async/await/Task を使った非同期呼び出し」とコメントしたところを見て
ください。

デリゲートを利用した非同期メソッドの実装
http://surferonwww.info/BlogEngine/post/2019/06/19/coding-asynchronous-method-by-using-delegate-in-windows-forms-application.aspx

引用返信 編集キー/
■93854 / inTopicNo.5)  Re[2]: 非同期処理の考え方
□投稿者/ ダージリン (2回)-(2020/02/12(Wed) 10:23:17)
みなさん、ありがとうございます。

たとえば、複数ファイルを読み込みつつ、
重い処理をした結果を表示するような場合を考えます。

ファイル読み込み時は例外から逃げられませんので、
以下のような感じで考えればよいのかな?

private async void Func()
{
foreach(複数ファイルのパス群)
{
try
{
await ファイルの読み込み();
}
catch (FileNotFoundException e1)
{
警告表示();
continue;
}
catch (IOException e2)
{
警告表示();
continue;
}
await 重い処理();
結果表示();
}
}
引用返信 編集キー/
■93855 / inTopicNo.6)  Re[3]: 非同期処理の考え方
□投稿者/ ダージリン (3回)-(2020/02/12(Wed) 10:24:00)
図表モードで再投稿します。

みなさん、ありがとうございます。

たとえば、複数ファイルを読み込みつつ、
重い処理をした結果を表示するような場合を考えます。

ファイル読み込み時は例外から逃げられませんので、
以下のような感じで考えればよいのかな?

private async void Func()
{
    foreach(複数ファイルのパス群)
    {
        try
        {
            await ファイルの読み込み();
        }
        catch (FileNotFoundException  e1)
        {
            警告表示();
            continue;
        }
        catch (IOException e2)
        {
            警告表示();
            continue;
        }
        await 重い処理();
        結果表示();
   }
}

引用返信 編集キー/
■93856 / inTopicNo.7)  Re[4]: 非同期処理の考え方
□投稿者/ ダージリン (4回)-(2020/02/12(Wed) 10:28:51)
UIスレッドから呼び出したとして、
イメージとしては、
    await ファイルの読み込み();
    await 重い処理();
の処理中は、画面操作が可能で、
それ以外の同期処理中は画面操作ができない。
という認識でよい?

引用返信 編集キー/
■93857 / inTopicNo.8)  Re[5]: 非同期処理の考え方
□投稿者/ WebSurfer (2025回)-(2020/02/12(Wed) 10:44:29)
No93856 (ダージリン さん) に返信
> UIスレッドから呼び出したとして、
> イメージとしては、
> await ファイルの読み込み();
> await 重い処理();
> の処理中は、画面操作が可能で、
> それ以外の同期処理中は画面操作ができない。
> という認識でよい?

質問の意味が十分理解できませんが・・・

マルチスレッドアプリは OS がスレッドを自動的に高速で切り替えながら処置しているという
ことで、UI スレッドに切り替えられた時は画面操作ができるという話です。

UI スレッドで重い処置をしているとその処置が終わるまで画面操作ができない(私が紹介し
た記事の「同期呼び出し」のコード参照)ということになります。

実際に自分でサンプルコードを作って試してみることをお勧めします。
引用返信 編集キー/
■93858 / inTopicNo.9)  Re[5]: 非同期処理の考え方
□投稿者/ Hongliang (959回)-(2020/02/12(Wed) 10:45:30)
「画面操作」というのがユーザのマウス等による入力のこととして、正確には
「マウス等の入力メッセージがメッセージキューから取り出されない」
ですが、おおざっぱにはそんな感じの理解でよいかと思います。

// プログラムからTextを変更したりするのも「画面操作」と表現できます。
引用返信 編集キー/
■93859 / inTopicNo.10)  Re[6]: 非同期処理の考え方
□投稿者/ ダージリン (5回)-(2020/02/12(Wed) 10:53:44)
ありがとうございます。
だいたい分かったような気がします。

後は、やってみながら確認したいと思います。

ありがとうございました(^-^)

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -