2016-10-12 5 views
0

私は以下のようなコードを持っています。私はUI Hung問題に直面しています。それを再現する直接の方法はありません。その発生は無作為に1回10回起こる。私は問題の原因を特定できません。C#WPF UI Freeze Issue MultiThreading

私は子ウィンドウが表示されますボタンクリックコードの下にあります。 -

private void processCart_Click(object sender, RoutedEventArgs e) 
{ 
    // processcart is Child Window Like Dialog To Open on Top Of Main Window 
    processcart = new ProcessCart(); 

    processcart.Closed += ProcessCart_OnClosed; 

    // Disable Parent Window 
    this.Dispatcher.Invoke(new Action(() => 
    { 
     try 
     { 
      this.IsEnabled = false; 
     } 
     catch (Exception ex) 
     { } 
    })); 

    processcart.Owner = Window.GetWindow(this); 

    // Openning Child Window 
    processcart.Show(); 
} 

private void ProcessCart_OnClosed(object sender, EventArgs e) 
{ 
    // On Child Window Close Doing some UI Update on Main Window 
    totalChangeAmount.Dispatcher.Invoke(new Action(() => 
    { 
     try 
     { 
      totalChangeAmount.Text = XFuelMath.roundingTwo(cart.ChangeTotal) + ""; 
     } 
     catch 
     { } 
    })); 

    // Starting Background Worker Thread for Database operation. 
    if (!bgwTransaction.IsBusy) 
    { 
     bgwTransaction.RunWorkerAsync(cart); 
    } 
} 

private void bgwTransaction_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // Doing some database operation but no UI Operation 

    // I dont know if i can call task inside background worker. 
    Task.Run(() => DeleteCurrentTicketDataFromDB(dataList, false)); 

    // Calling another background worker inside it 
    if (!bgwPrintRecipt.IsBusy) 
    { 
     bgwPrintRecipt.RunWorkerAsync(); 
    } 
} 

private void bgwPrintRecipt_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // Sending Data to printer 
} 

private void bgwPrintRecipt_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    // No Ui Operation Here 
} 

private void bgwTransaction_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    // Some UI Operation 
    totalSurcharge.Dispatcher.Invoke(() => 
    { 
     totalSurcharge.Text = "0"; 
    }); 

    saleNumber.Dispatcher.Invoke(() => { }); 

    saleDataGrid.Dispatcher.Invoke(new Action(() => 
    { 
     try 
     { 
      saleDataGrid.ItemsSource = currentSharedTicketCollection; 
      saleDataGrid.Items.Refresh(); 

      if (isautoscroll && item!=null) 
      { 
       saleDataGrid.ScrollIntoView(item, saleDataGrid.Columns[0]); 
       saleDataGrid.SelectedItem = item; 
      } 
     } 
    })); 

    // Enable the parent window Again 
    this.Dispatcher.Invoke(new Action(() => 
    { 
     try 
     { 
      this.IsEnabled = true; 
     } 
     catch (Exception ex) 
     { } 
    })); 
} 

私はBackgroundWorkerを呼び出していた場合に確認していない内部DoWorkRunWorkerCompletedを行います。 このコードで変更する必要があるものを教えてください。

+0

私はすべての空のキャッチブロックを取り除くことから始めたいと思います。 –

+0

キャッチブロックにいくつかのロギングコードがあるので、投稿中に削除しました。コードを短くする。 –

+0

BackgroundWorkerとTask.Runを混在させるだけで、頭痛の原因になります。どちらか一方を選択してください。 –

答えて

1

processCart_ClickハンドラでDispatcherの呼び出しを削除する必要があります。これは、同じUIスレッドで実行され、別のスレッドに複数のWPFウィンドウが作成されている場合を除き、まったく必要ありません。

さらに、ハングしたプロセスにデバッガを接続し、ハングする場所を確認する必要があります。実行されているマシンにデバッガがインストールされていない場合は、タスクマネージャを右クリックしてダンプファイルを作成します。そのファイルはVisual Studioに読み込むことができます。

アプリケーションがWindows x64上で実行されている32ビットアプリケーションの場合、64ビットWindows上で32ビットダンプを取るには、タスクマネージャを閉じてC:\ Windows \ SysWOW64 \ Taskmgr.exeから起動する必要があります。これを行わなければ、マネージドコールスタックを使ってVSにロードすることはできません。

+0

RunWorkerCompletedでDispatcherを使用するのは正しいですか?または、私もそれを必要としません –

+0

あなたのワーカーが別のスレッドで実行されている場合は、UIスレッドにコールするディスパッチャの呼び出しが必要です。それらを削除すると、あなたが作成されたものとは別のスレッドからコントロールにアクセスしようとしたことを通知する例外が発生します。 –

+0

私はexeファイルをユーザに与えて、デバッグシンボルとしてpdbファイルを含めました。タスクマネージャーで生成されたダンプファイルを取得し、ハングした問題を確認するには、このファイルをexeに含める必要がありますか? –