0

ディスパッチャーをスレッドでラップしようとしました。しかし、結果は私が期待するものではありません。どうすればその問題を解決できますか?

    public void Start()
    {
        ThreadStart ts = inner;
        Thread wrapper = new Thread(ts);
        wrapper.Start();
    }

    private void inner()
    {
        _Runner.Dispatcher.Invoke(_Runner.Action, DispatcherPriority.Normal);
    }
4

7 に答える 7

5

あなたは適切な回答を提供するのに十分なほど十分なコードや説明を私たちに示していませんが、あなたのアクション ( _Runner.Action) はコストがかかり、実行が遅いと思います。その場合、UI が応答しないのはそのためです。基本的に、Dispatcher に、UI スレッドでその高価な操作を実行するように指示しています。実際にやりたいことは、できるだけ多くの操作をバックグラウンド スレッドで実行し、Dispatcher必要な場合にのみを介して UI スレッドにマーシャリングすることです。 .

于 2009-06-10T12:05:56.923 に答える
2

ディスパッチャーを介してアクションを起動すると、そのアクションは UI スレッドで呼び出されます。

私の推測では、_Runner.Action関数で作業/処理を行っており、UI スレッドを結び付けています。関数でメインの処理部分を実行してからinner()、Dispatcher を呼び出して最終的な更新の詳細を取得する必要があります。

どうしてもディスパッチャで処理する必要がある場合は、プロセスを細かく分割し、各部分に対して Dispatcher.BeginInvoke() を呼び出して、プロセス間で他のイベントを処理できるようにします。

于 2009-06-10T12:06:13.473 に答える
2

Runner.Action を 2 つの部分 (計算を行う長期実行部分と GUI を更新する部分) に分割する必要があります。

その後、バックグラウンド スレッドで実行時間の長い部分を呼び出し、UI 更新部分でのみディスパッチャを使用します。

ちなみに、おそらく Invoke ではなく BeginInvoke を使用する必要があります。

Runner.Action の実行時間の長い部分が GUI を更新している場合、バックグラウンド スレッドを使用して問題を解決することはできません。遅い GUI 操作の解決策はありますが、実際に何をしようとしているかによって異なります。

于 2009-06-10T14:55:37.423 に答える
1

ここのみんなが言ったことと同じです。

さらに、BackgroundWorkerクラスの使用を検討することもできます。

于 2009-06-10T17:18:40.863 に答える
1

これは私がバックグラウンドタスクに使い始めたものです...私はそれを長く使用していないので、バグがあるかどうかはわかりません.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SSA.Utility
{
    public class BackgroundTaskManager : IDisposable
    {
        private System.Windows.Threading.Dispatcher _OwnerDispatcher;
        private System.Windows.Threading.Dispatcher _WorkerDispatcher;
        private System.Threading.Thread _WorkerThread;
        private Boolean _WorkerBusy;

        private System.Threading.EventWaitHandle _WorkerStarted = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.ManualReset);

        public BackgroundTaskManager()
        {
            _OwnerDispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
            _WorkerThread = new System.Threading.Thread(new System.Threading.ThreadStart(WorkerStart));
            _WorkerThread.Name = "BackgroundTaskManager:" + DateTime.Now.Ticks.ToString();
            _WorkerThread.IsBackground = true;
            _WorkerThread.Start();

            _WorkerStarted.WaitOne();
        }

        public Boolean IsBusy
        {
            get { return _WorkerBusy; }
        }

        public System.Windows.Threading.Dispatcher Dispatcher 
        {
            get {
                return _WorkerDispatcher;
            }
        }

        public System.Windows.Threading.Dispatcher OwnerDispatcher
        {
            get
            {
                return _OwnerDispatcher;
            }
        }


        private void WorkerStart()
        {
            _WorkerDispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
            _WorkerDispatcher.Hooks.DispatcherInactive += WorkDone;
            _WorkerDispatcher.Hooks.OperationPosted += WorkAdded;
            _WorkerStarted.Set();
            System.Windows.Threading.Dispatcher.Run();
        }

        private void WorkAdded(Object sender, System.Windows.Threading.DispatcherHookEventArgs e)
        {
            _WorkerBusy = true;
        }

        private void WorkDone(Object sender, EventArgs e)
        {
            _WorkerBusy = false;
        }

        public void Dispose()
        {
            if (_WorkerDispatcher != null)
            {
                _WorkerDispatcher.InvokeShutdown();
                _WorkerDispatcher = null;
            }
        }

    }
}


// Useage (not tested)

private SSA.Utility.BackgroundTaskManager _background = new SSA.Utility.BackgroundTaskManager();

public void LongTaskAsync() 
{
  _background.Dispatcher.BeginInvoke(new Action(LongTask), null);
}

public void LongTask() 
{
   System.Threading.Thread.Sleep(10000); // simulate a long task
   _background.OwnerDispatcher.BeginInvoke(new Action<STATUSCLASS>(LongTaskUpdate), statusobject);
}

public void LongTaskUpdate(STATUSCLASS statusobject) {

}
于 2011-08-22T16:24:36.513 に答える
1

複数の UI スレッドで WPF アプリケーションを実行できる例を次に示します。私はこれがあなたを助けると信じています. これを参照してください http://eprystupa.wordpress.com/2008/07/28/running-wpf-application-with-multiple-ui-threads/

Thread lThread = new Thread(() =>
                   {
                        var lWnd = new Window1();
                        lWnd.Show();
                        lWnd.Closed += (sender2, e2) => lWnd.Dispatcher.InvokeShutdown();
                        System.Windows.Threading.Dispatcher.Run();
                   });
lThread.SetApartmentState(ApartmentState.STA);
lThread.Start();
于 2009-06-10T14:43:50.723 に答える
0

はい。_Runner.Action が問題です。Dispatcher ブロックで使用されるいくつかの長時間のメソッド。しかし、解決策は「ディスパッチャーでUIに関係のないスレッドを使用しない」ことです

于 2009-06-10T12:53:58.527 に答える