我想实现一个Parallel.ForEach循环替换旧foreach循环,但我无法更新我的UI(我有显示类似“X/Y文件处理”一个计数器)。我做了一个Parallel.For循环的例子来说明我的问题(标签没有被更新)。c#Parallel.For和UI更新?
using System;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Threading;
namespace FormThreadTest
{
public partial class Form1 : Form
{
private SynchronizationContext m_sync;
private System.Timers.Timer m_timer;
private int m_count;
public Form1()
{
InitializeComponent();
m_sync = SynchronizationContext.Current;
m_count = 0;
m_timer = new System.Timers.Timer();
m_timer.Interval = 1000;
m_timer.AutoReset = true;
m_timer.Elapsed += new System.Timers.ElapsedEventHandler(m_timer_Elapsed);
m_timer.Start();
}
private void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Task.Factory.StartNew(() =>
{
m_sync.Post((o) =>
{
label1.Text = m_count.ToString();
Application.DoEvents();
}, null);
});
}
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
Parallel.For(0, 25000000, delegate(int i)
{
m_count = i;
});
});
}
}
}
如果我改变按钮单击事件方法,并添加了Thread.Sleep(),它似乎给时间UI更新线程来完成其工作:
private void button1_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
Parallel.For(0, 25000000, delegate(int i)
{
m_count = i;
Thread.Sleep(10);
});
});
}
是有没有办法避免睡眠,还是我需要在那里?这似乎是我的用户不会更新标签,除非我这样做?我觉得奇怪,因为我可以将应用程序窗口(它不锁) - 那么,为什么惯于标签更新了,我怎么可以改变我的代码,以更好地支持的Parallel.For(每个)和UI更新?
我一直寻找一个解决方案,但我不能似乎发现了什么(或者我可能寻找错误的东西?)。
问候 西蒙
我对这个知之甚少,但是这可能与允许的线程数有关吗?如果Parallel.For将他们全部拿走并且不留下任何事件来抓取,那么这可以解释行为。但我对此并不确定,所以它真的只是一个疯狂的猜测,希望能激发一个知道更多的人。 :) – Chris 2011-01-24 14:36:52
尝试在设置标签文本后放置Application.DoEvents()。这将让其他线程(特别是UI线程)有机会重画屏幕 – user2712361 2013-08-23 20:45:00