【发布时间】:2015-11-29 17:08:03
【问题描述】:
我正在尝试更新 UI 上的状态以进行长时间运行。我创建了一个基于演示表单的应用程序,任务它有多行,每一行都有天,数据网格的每一列中的默认值为 0,一旦计算文件计算了一天的一次迭代,它将更新 UI 并为此设置 1日。
我正在使用线程、委托和事件来实现这一点,如果我将 Thread.Sleep(100) 放在两个事件调用之间,它会按预期工作。如果我将“Thread.Sleep(100)”放在最后一个嵌套的 for 循环中,那么它会按预期更新 UI,但是一旦我删除它并在没有睡眠的情况下运行循环,它就会跳过 UI 上的一些列并直接更新最后几个/随机列,正如您在附加的图像链接中看到的(我的代码的输出图像没有线程睡眠)只有最后一列正在更新。
如果我没记错的话,所有事件都是按顺序触发的,那么它们也应该按顺序更新 UI,但它没有发生,我不知道为什么。我不想做这个睡眠的事情,因为我在实际应用程序中有大约 14 次调用 UI 状态更新,它会在一个循环下运行,所以如果它放 sleep(100) 那么它会花费我很多,有什么办法吗不睡觉?
Image of output of my code without thread sleep
public class Class1 : IGenerate
{
public event MessageEventHandler OnMessageSending;
public void LongOperationMethod(BindingList<Status> _statusData)
{
if (OnMessageSending != null)
{
MessageEventArgs me = new MessageEventArgs();
/// Loop for 2-3 Weeks
for (; ; ){
/// Loop for 7 day
for (; ; )
{
/// Calculation on everyday
for (int j = 0; j != 1000; ++j)
{
// to do
}
me.weekNo = k;
me.DayNo = i;
OnMessageSending(me);
}
}
me.Message = "Process completed successfully...";
OnMessageSending(me);
}
else
{
throw new ArgumentException("Event hasn`t been rised, so we cannot continue working.");
}
}
}
**UI file:**
<pre><code>
public partial class Form1 : Form
{
BindingList<Status> _statusData = new BindingList<Status>();
delegate void StringParameterDelegate(string value);
Class1 cls = new Class1();
public Form1()
{
InitializeComponent();
labelProgress.Text = "";
}
private void button1_Click_1(object sender, EventArgs e)
{
for (int i = 1; i <= 2; ++i)
{
_statusData.Add(new Status { Week = "Week" + i, Day1 = 0, Day2 = 0, Day3 = 0, Day4 = 0, Day5 = 0, Day6 = 0, Day7 = 0 });
}
dataGridView1.DataSource = _statusData;
}
private void button2_Click(object sender, EventArgs e)
{
Thread t1 = new Thread(() => StartingThread(_statusData));
t1.Start();
}
void StartingThread(BindingList<Status> _statusData)
{
IGenerate generate = new Class1();
generate.OnMessageSending += new MessageEventHandler(generate_OnMessageSending);
generate.LongOperationMethod(_statusData);
}
private void generate_OnMessageSending(MessageEventArgs e)
{
int weekNo = e.weekNo;
int dayNo = e.DayNo;
this.dataGridView1.BeginInvoke(new MethodInvoker(() => dataGridView1.Rows[e.weekNo].Cells[e.DayNo + 1].Value = 1));
this.labelProgress.BeginInvoke(new MethodInvoker(() => this.labelProgress.Text = e.Message));
}
}
</code></pre>
【问题讨论】:
标签: c# multithreading events delegates