2017-07-26 6 views
0

背景スレッディングは、まだ現在、私が作成するように求めWindowsフォームアプリケーションに取り組んで

私のUI凍結されます。リソース集中型のプロセスが呼び出されているときにUIがフリーズする問題が発生しました。私は現在、UIがフリーズしてPC全体を占有するのを防ぐために、私が理解しているスレッドを使用しています。

質問私は、リモートサーバーにあるファイルを開くことです私の基本クラスのメソッドを呼び出すためにスレッドを使用しています現在

。この方法の遅延時間は約30〜45秒です。バックグラウンドスレッドを作成して起動するように呼びかけています。起動時に呼び出されたときに起動すると、起動したときにスレッドが完了するのを待たずに、基本的にnull例外が返されます。だから掘り下げた後、スレッドが完了するのを待つために、.Join()を呼び出さなければならないことがわかった。しかし、結合が呼び出されると、UIが完全にフリーズします。だから私の創意工夫は、周りの作業を作成しようとし、スレッドがもはや生きていなくても継続するwhileループを作成しました。しかし、これによってUIも凍結されました。私は何かを逃していますか?それはMSDN Doc

コードサンプル

class BaseClass 
{ 
    public CWClient ClientFileContext(string clientFile, bool compress) 
    { 
     Client clientContext = null; 
     try 
     { 
      if (compress == true) 
      { 
       clientContext = appInstance.Clients.Open2(clientFile, superUser, passWord, OpenFlags.ofCompressed); 
      } 
      else 
      { 
       clientContext = appInstance.Clients.Open2(clientFile, superUser, passWord, OpenFlags.ofNone); 
      } 
     } 
     catch (Exception ex) 
     { 
      //TODO 
     } 
     return clientContext; 
    } 
} 

    public partial class Form1 : Form 
    { 
    private void button1_Click(object sender, EventArgs e) 
    { 
     BaseClass wpSec = new BaseClass(); 
     CWClient client = null;    

     Thread backgroundThread = new Thread(
      new ThreadStart(() => 
      { 
       client = wpSec.ClientFileContext(selectedFileFullPath, true); 
      } 
     )); 
     backgroundThread.Start(); 
     //backgroundThread.Join(); << Freezes the UI 
     var whyAreYouNotWorking = "Stop"; 
    } 
    } 

には言及していない私の周りの仕事は、私もこのためasyncawaitパターンになります

while (backgroundThread.IsAlive == true) 
{ 
    for (int n = 0; n < 100; n++) 
    { 
     Thread.Sleep(500); 
     progressBar1.BeginInvoke(new Action(() => progressBar1.Value = n)); 
    } 
} 
    // This also freezes the UI 
+1

はい、結合(開始直後)は、スレッド設定全体を否定します。あなたは何を期待しましたか?また、Control.Invoke()呼び出しをデッドロックします。 –

+1

ここで簡単な答えは、BackgroundWorker –

+0

を使用することです。UIスレッドをブロックし、バックグラウンド作業が終了するまで何もしないようにすると、UIはフリーズし、そうでないときはフリーズします。だからあなたの質問は何ですか?あなたはすでにあなたの問題を解決する方法を知っています* UIスレッド*をブロックしないでください。 UIスレッドを自分でブロックしないようにコードを示しています。 – Servy

答えて

3

を試してみました。この記事で説明:Using async await still freezes GUI

あなたのコードは(基底クラスは変更されません)このようになります。

public partial class Form1 : Form 
{ 
    private async void button1_Click(object sender, EventArgs e) 
    { 
     BaseClass wpSec = new BaseClass(); 
     CWClient client = await Task.Run(() => 
      { 
       return wpSec.ClientFileContext(selectedFileFullPath, true); 
      } 
    ); 
     var whyAreYouNotWorking = "Stop"; 
    } 
} 

これは、バック・オブ・エンベロープのものですが、うまくいけば、それは基本的なアイデアを提供しますタスクを起動してからasyncメソッドの結果を待っています。あなたのBaseClassがぶら下がっている必要がなければ、それはラムダにもあり得ます。あなたが本当に望むものだけを残します。

@Chris Dunawayからのリンクも優れています。 http://blog.stephencleary.com/2013/08/taskrun-vs-backgroundworker-round-3.html

編集:@BradlyUffnerが言及したように、これはまた、あなたがasync voidを使用する必要がありますし、むしろ、ほぼすべての他の状況でTaskまたはTask<T>を返す好むべきで数回の一つです。

+0

この回答を読んでいる人には、 'async void 'を使うべき有効な場所のほんの少数しか示されていないことに注意してください。 'async'を理解していない限り、' async'以外のものは 'Task'または' Task 'を返すべきです。 –

+0

私が読んでいたことから、私は別のアプローチをとって作った基本クラスの私の関数は非同期タスクです。それはあなたのやり方で利益をもたらすのですか?コード例を更新します。 – EasyE

+0

Fair point @ BradleyUffner、私が同意する通り、あなたが言うようにしなければなりません。私はそれを編集して言及します。 –

関連する問題