我试图在UI上更新长期运行操作的状态。我创建了一个基于演示表单的应用程序,任务它有多行,每行都有几天,每行datagrid中的默认值为0,一旦计算文件计算一天的迭代,它将更新UI并设置1那天。
我正在使用线程,委托和事件来实现它,如果我在两个事件调用之间放置Thread.Sleep(100),它正在按预期工作。如果我把" Thread.Sleep(100)"在最后一个嵌套for循环中然后它按预期更新UI但是一旦我删除它并在没有睡眠的情况下运行循环,那么它会跳过UI上的一些列并直接更新最后几个/随机列,如附图所示(没有线程休眠的我的代码的输出图像)只有最后一列正在更新。
如果我没有弄错,所有的事件都按顺序被解雇,那么他们也应该按顺序更新UI,但它没有发生,我不知道为什么。我不想做这个睡眠的事情,因为我在实际应用程序中有大约14个调用UI状态更新,它将在一个循环下运行所以如果它放入睡眠(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>
答案 0 :(得分:1)
看起来你每次都发送function dataSort(columnNum) {
var artDataTable = document.getElementById('table');
var dataArray = [];
for (var I = 1; I < artDataTable.rows.length; i++) {
var r = artDataTable.rows[i];
var rowData = r.cells[columnNum].innerText;
dataArray.push([rowData, r]);
}
dataArray.sort();
for (var j = 0; j < dataArray.length; j++) {
artDataTable.appendChild(dataArray[j][1]);
}
dataArray = null;
}
的同一个实例,只是在后台线程上更新那个实例。这意味着UI线程上的事件处理程序将检索循环中正在更新的MessageEventArgs
的完全相同的实例!当您的UI处理程序获得MessageEventArgs
时,其MessageEventArgs
和.weekNo
属性很可能已被循环的下一次迭代修改,因为它们在不同的线程上运行。
要解决此问题,请在每次致电.DayNo
时创建MessageEventArgs
的新实例。
相关摘要:
OnMessageSending()