1

編集#1:タイマーループ内にworker.RunWorkerAsync()を配置しましたが、アプリケーションがシャットダウンしなくなりました。今は何も起こらないようですが。

パフォーマンス上の理由から、DispatcherTimersを別のスレッドで実行される他のタイマーに置き換える必要があります。多くの遅延/フリーズがあるため、DispatcherTimerはオプションではなくなりました。

GUIスレッドを実際に更新するのに問題があります。アプリケーションは、警告やエラーなしで常にシャットダウンしているようです。 私は主に、問題を解決するためにBackGroundWorkerを試してみました。アプリケーションを起動すると、すべてがアプリケーションのシャットダウンにつながります。

いくつかのコード例は非常に魅力的です。

古いコードディスパッチャーコード:

    public void InitializeDispatcherTimerWeging()
    {
        timerWegingen = new DispatcherTimer();
        timerWegingen.Tick += new EventHandler(timerWegingen_Tick);
        timerWegingen.Interval = new TimeSpan(0, 0, Convert.ToInt16(minKorteStilstand));
        timerWegingen.Start();
    }

    private void timerWegingen_Tick(object sender, EventArgs e)
    {
        DisplayWegingInfo();
        CaculateTimeBetweenWegingen();
    }

5秒ごとに、DisplayWegingInfo()およびCalculateメソッドを呼び出す必要があります。

GUIの更新は、Calculateメソッドで行われます。ボタンが動的に作成され、observerableCollectionに追加されます。

ボタンの作成(ショートバージョン):

    public void CreateRegistrationButton()
    {
        InitializeDispatcherTimerStilstand();

        RegistrationButton btn = new RegistrationButton(GlobalObservableCol.regBtns.Count.ToString());
        btn.RegistrationCount = GlobalObservableCol.regBtnCount;
        btn.Title = "btnRegistration" + GlobalObservableCol.regBtnCount;
        btn.BeginStilstand = btn.Time;

        GlobalObservableCol.regBtns.Add(btn);
        GlobalObservableCol.regBtnCount++;

        btn.DuurStilstand = String.Format("{0:D2}:{1:D2}:{2:D2}", 0, 0, 0);         
    }

GUIとは異なるスレッドで実行されるスレッドタイマーを使用した新しいコード

    public void InitializeDispatcherTimerWeging()
    {
        worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
        worker.RunWorkerAsync();
    }

    void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        TimerCallback callback = MyTimerCallBack;
        timerWegingen = new Timer(callback);

        timerWegingen.Change(0, 5000);
    }


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

タイマーは別のスレッドで実行され、次にGUIスレッド(dispatcherTimerが使用する)で実行されます。しかし、この更新をUIスレッド自体に送信できないようであるため、更新は実際にUIに実装されます。

ボタンは、他のタイマーを介して1秒ごとに新しい値で再入力されます。「DuurStilstand」は依存関係のプロパティです

    private void FillDuurStilstandRegistrationBtn()
    {
        TimeSpan tsSec = TimeSpan.FromSeconds(stopWatch.Elapsed.Seconds);
        TimeSpan tsMin = TimeSpan.FromMinutes(stopWatch.Elapsed.Minutes);
        TimeSpan tsHour = TimeSpan.FromMinutes(stopWatch.Elapsed.Hours);

        if (GlobalObservableCol.regBtns.Count >= 1
                    && GlobalObservableCol.regBtns[GlobalObservableCol.regBtns.Count - 1].StopWatchActive == true)
        {
            GlobalObservableCol.regBtns[GlobalObservableCol.regBtns.Count - 1].DuurStilstand =
                            String.Format("{0:D2}:{1:D2}:{2:D2}", tsHour.Hours, tsMin.Minutes, tsSec.Seconds);
        }
    }

上記のメソッドでDispatcherからの呼び出しを使用する必要がありますか?もしそうなら、どのくらい正確に?

BackGroundWorkerのdoWorkメソッドを初期化した後、UIスレッドを呼び出す方法がわからないため、起動直後にアプリケーションがシャットダウンし続けます。Dispatcher.BeginInvokeをいくつかの方法で使用しようとしましたが、これまでのところすべて失敗しました。現時点では、それを実装する方法がわかりません。

上記のコードはすべて、別のc#クラスで記述されています。

よろしく、ジャックズ

4

1 に答える 1

1

コードのサンプルを実行したところ、DisplayWegingInfo() が UI コンポーネントにアクセスしようとして例外をスローしていました。UI を更新するには、Timer スレッドから Invoke() を呼び出す必要があります。以下の DisplayWegingInfo() を参照してください。注: これは、CaculateTimeBetweenWegingen() が UI と対話しないことを前提としています。

   void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        TimerCallback callback = MyTimerCallBack;
        timerWegingen = new System.Threading.Timer(callback);
        timerWegingen.Change(0, 3000);

    }

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

    private void DisplayWegingInfo()
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new Action(DisplayWegingInfo));
            return;
        }

        // at this point, we are on the UI thread, and can update the GUI elements
        this.label1.Text = DateTime.Now.ToString();
    }

    private void CaculateTimeBetweenWegingen()
    {
        Thread.Sleep(1000);
    }
于 2012-04-17T13:41:42.183 に答える