0

重複の可能性:
C# で別のスレッドから GUI を更新するには?

スレッド化されたクラスから UI を更新するにはどうすればよいですか? スレッドから更新フォーム コントロールにアクセスできません。特定の各スレッドの進行状況で UI を更新したいと思います。

class MyClass
    {
        public delegate void CountChangedEventHandler(int vCount, int vIndex);
        public event CountChangedEventHandler CountChanged;

        private int count;
        private int index;

        public MyClass(int index)
        {
            this.index = index;
        }

        public int Count
        {
            get { return this.count; }
            set
            {
                this.count = value;
                if (this.CountChanged != null)
                    this.CountChanged(value, this.index);
            }
        }

        public void DoWork(object o)
        {
            for (int i = 0; i < 10000; i++)
            {
                this.Count = i;
            }
        }
    }

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < 3; i++)
            {
                MyClass myCount = new MyClass(i);
                myCount.CountChanged += new MyClass.CountChangedEventHandler(UpdateUI);

                ListViewItem lvi = new ListViewItem();
                lvi.Text = "Thread #" + i.ToString();
                lvi.SubItems.Add("");
                listView1.Items.Add(lvi);

                ThreadPool.QueueUserWorkItem(new WaitCallback(myCount.DoWork));

            }
        }

        private void UpdateUI (int index, int count)
        {
            listView1.Items[index].SubItems[0].Text = count.ToString();
        }
    }
4

2 に答える 2

1

UI アクセスを使用するInvokeBeginInvoke、UI スレッドにマーシャリングする必要があります。

このインスタンスで使用することをお勧めしInvokeます。これにより、ループが先に進みすぎるのを防ぐことができます。

private void UpdateUI (int index, int count)
{
  Invoke( ( MethodInvoker ) (
    () => listView1.Items[index].SubItems[0].Text = count.ToString()
  ) );
}
于 2013-01-14T16:36:58.723 に答える
0

これを実現するには、複数の方法があります。以下にいくつかのオプションを示します。

1) BackgroundWorker - これを使用する方法についてオンラインで多くの例を見つけることができ、プロセス中に進行状況 (整数) を UI に戻すだけでよい場合に限り、受け入れられます。

2) タイマー付きのメッセージ キュー - 進行状況だけでなく、UI に戻すオプションを提供します。

これは、文字列を UI に戻す、私が作成した WPF アプリケーションのオプション 2 の例です。もちろん、文字列を任意のカスタム オブジェクトに置き換えることができます。また、.NET 3.0 以降が必要です。

private static List<string> MessageQueue = new List<string>();

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    DispatcherTimer messageQueueTimer = new DispatcherTimer();
    messageQueueTimer.Tick += messageQueueTimer_Elapsed;
    messageQueueTimer.Interval = new TimeSpan(1); //1 tick
    messageQueueTimer.Start();
}

protected void messageQueueTimer_Elapsed(object sender, EventArgs e)
{
    lock(MessageQueue)
    {
        //Read message from queue and remove it.
    }
}

//WriteLine can be called from any asyncronous method spawed from the UI.
public void WriteLine(string message)
{
    lock(MessageQueue)
    {
        //Insert message into the queue.        
    }
}

これを実現する方法は他にもいくつかありますが、これで始めることができます。お役に立てれば!

于 2013-01-14T16:48:51.663 に答える