2012-04-16 9 views
4

私は、スレッドタイマーに私のDispatcherTimer構文を変換する問題を抱えています。私のアプリケーションを突然実行すると、エラーなしでシャットダウンします。System.Threadingタイマー

基本的には、タイマーは5秒ごとに2つの方法を実行します。

編集:2つの方法でUIが更新されています。 私は私がずっとフリーズし、UI表示の遅れを持っているので、DispatcherTimerを取り除くしようとしようとしています。

ディスパッチャタイマーコード:System.Threadingタイマーのための

timerW = new DispatcherTimer(); 
    timerW.Tick += new EventHandler(timerW_Tick); 
    timerW.Interval = new TimeSpan(0, 0, 5000); 
    timerW.Start(); 



private void timerW_Tick(object sender, EventArgs e) 
     { 
      DisplayWegingInfo(); 
      CaculateTimen(); 
     } 

コード:

public void InitializeDispatcherTimerW() 
    { 
     TimerCallback callback = MyTimerCallBack; 
     timerW = new Timer(callback); 

     timerW.Change(0, 5000); 
    } 

    private void MyTimerCallBack(object state) 
    { 
     DisplayWegingInfo(); 
     CaculateTime(); 
    } 

感謝。

+0

Debug.Printのように、実行中の2つの関数をコメントアウトし、それらを一時的に無害なものに置き換えます。私がすでにタイマーを2回初期化してしまっていることは少し難解ですが、あなたがすでに示したコードのクラッシュを想像することはできません。 –

+0

私はディスパッチャタイマを取り除こうとしています。なぜなら、ディスパッチャタイマはアプリケーションで多くの遅延を生み出すからです。私がMyTimerCallBackにコメントするとき、アプリケーションはもはやシャットダウンしません。これらの2つのメソッドは、UIを更新しようとします。 – Jackz

+1

['BackgroundWorker'](http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx)がこれにもっと適しているかもしれません。いずれにしても、あなたのタイマースレッドからのUIへの更新は、 'Control.Invoke'を使ってのみ安全に行うことができます。 –

答えて

2

DisplayWedgingInfoという名前で判断すると、このメソッドはUIを更新すると思いますか? System.Threading.Timerは、UIスレッドとは異なるスレッドで実行されるため、そのスレッドからUIを更新できるようにするには、Dispatcher::[Begin]Invokeを使用して、それらの呼び出しをDispatcherスレッドに戻してマーシャリングする必要があります。

だから、あなたは高価なものは何でもあるようなUI要素には触れませんが、UI操作のためのあなたは、単にだろう作業残すことができます:私はいずれにもいくつかの中断があることを指摘しなければならない

string someValue = this.SomeExpensiveOperation(); 

this.Dispatcher.BeginInvoke(
    DispatcherPriority.Background, 
    new Action(() => 
    { 
      this.myControl.Text = someValue; 
    })); 

呼び出しが発生したときに実行される可能性のあるUIのインタラクション/レンダリング。これは、実行がメインスレッド上で行われるため避けがたいことです。 DispatcherPriority.Backgroundを使用すると、ユーザーがその時点で提供している可能性のある入力よりも優先順位を低く保つ優先度で更新をスケジュールする必要があります。ただし、罰金なしにUIを大幅に更新することはできません。これを行うために必要がある場合には、必要に応じて、彼らが間に入力のような優先度の高いもので起こることができるようにBackground優先度で複数の呼び出しをキューするのが最善です。

+0

はい、UIを更新します。小さな事例を教えてください。乾杯 – Jackz

3

問題は、タイマーコールバックのメソッドでUIを更新している可能性があります。これはUIスレッドからのみ可能であり、タイマーはバックグラウンドスレッドで実行されます。

DispatcherTimerを貼っておくことをおすすめします。

コードを少し分けて解決する方法があります。作業集中型コードを他のメソッドに抽出し、バックグラウンドスレッドで実行し、後でUIスレッドからUIを更新します。このような

何か:

private void MyTimerCallBack(object state) 
{ 
    LongCalculationsThatDontNeedTheUI(); 
    _dispatcherUIThread.Invoke(new Action(UpdateUI)); 
} 
+0

私はdispatchertimerを使用するとき、私は多くの凍結と遅延があります。したがって、それを変える試み。 http://stackoverflow.com/questions/10175186/multiple-timers-wpf-application-the-calling-thread-must-be-sta-error – Jackz

+0

@ジャック:更新を参照してください。 –

-3

なぜ単純にイベントをディスパッチするためにバックグラウンドスレッドを使用していませんか?

CancellationTokenSource cts = new CancellationTokenSource(); 
    Task.Factory.StartNew(() => 
    { 
      while(!cts.IsCancellationRequested) 
      { 
       Thread.Sleep(5000); 

       this.Dispatcher.BeginInvoke(new Action(() => 
        { 
         DisplayWegingInfo(); 
         CalculateTimen(); 
        }), null); 
      } 
    }); 
+0

-1:これは、現在のアプローチと同じ問題を抱えています。バックグラウンドスレッドでUIを更新しようとしているため、失敗します。 –

+0

OPは、それらの機能でUIを更新しているとは言いませんでした。しかし、私はUIスレッドセーフなものになるように修正します。 – Tejs

+0

ディスパッチャで更新されました。 – Tejs

0

データ検索/計算データディスプレイから分離する必要があると思います。

Danielが指摘するように、GUI更新はDispatcherスレッドで行う必要があるため、最も簡単な方法はDispatcherTimerです。

DispatcherTimerを使用すると、タイマーコールバックのはすべてGUIスレッドで処理されます。を意味します。かなりの時間がかかる操作があれば、これはうまくいかない。あなたが見つけたように、GUIは吃音とロックアップします。

あなたは何が時間を費やしているかを理解する必要があります。あなたの他の質問から、私はそれがSQL検索であると推測します。この場合、実際に検索を別のスレッド(System.Threading.Timerを使用)で実行した方が良いでしょう。ディスプレイDispatcher.BeginInvoke()で更新してGUIスレッドにマーシャリングしてください。

0

1.私がUIを更新している場合は、ディスパッチャに戻ってきていることを確認してください - UIスレッドのみからUIを更新できます。データバインディングを使用している場合でも、タイマースレッドがUIにバインドされた値を更新すると、そのUIに触れる間違ったスレッドとしてカウントされます。

  1. try..catchブロックでタイムカードのコールバックを保護してください。処理されていない例外の.NETのデフォルト動作は、プロセスを終了することです。本当の原因はタイマースレッドやワーカースレッド上での例外処理ではありませんでした。 (実際には、間違ったスレッドからUIを操作しようとすると、WPFが例外をスローする必要があります。ハンドラがないので、プログラムが終了します)