我有一个winform,它有几个组合框和一个gridview。
最初我使用行和列创建gridview,并且没有填充数据。
填充数据到网格是一个长时间运行的任务,它将遍历所有行并读取列标题,并根据它将不同的颜色和数据应用于每个单元格。
我想要实现的是在表单加载事件中加载网格,并在表单加载后开始将数据填充到网格,以便用户可以看到发生了什么。同样的事情适用于组合框值的更改,因为我将根据组合值加载数据。
我试过的是这样的......
在表单加载中我正在调用方法
private void LoadForm()
{
DataBind(); // this will load the initial grid without cell data
this.BeginInvoke((MethodInvoker)this.LongRunningProcess1);
this.BeginInvoke((MethodInvoker)this.LongRunningProcess2);
}
但仍然需要很长时间,而且我没有响应式用户界面。
我也试过这样的事但没有运气......
ThreadStart ts = LongRunningProcess1;
Thread t1 = new Thread(ts);
t1.Start();
同样使用后台工作程序来完成长时间运行操作会导致 “跨线程操作” 问题。
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
LongRunningProcess1();
LongRunningProcess2();
}
任何使这项工作有所帮助的人都很感激..
谢谢
更新
我找到了一个非常酷的解决方案Updating Your Form from Another Thread without Creating Delegates for Every Type of Update
感谢您的回答!!!
答案 0 :(得分:1)
要避免后台工作程序的完成事件中的CrossThreadException,请将回调方法包装为:
public void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new RunWorkerCompletedEventHandler(WorkerCompleted), new {sender, e});
}
else
{
// Business logic goes here
}
}
通常,您将在else块中填充加载到GridView中的数据。另一方面,如果您希望从长时间运行的后台任务中逐步填充GridView,则可以使用来自后台工作程序的回调的类似技术来实现此目的:
public void Worker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (var someParameter in parameterList) // Long-running loop
{
var data = LoadData(someParameter); // Load data for row X
this.Invoke(new Action<object>(UpdateRow),new[]{data}); // Update on UI-thread
}
}
public void UpdateRow(object data)
{
// Code to populate DataGrid row X with data from argument
}
请注意,如果要异步进行UI更新,可以调用BeginInvoke而不是Invoke。在这种情况下,这通常没有区别。
答案 1 :(得分:0)
背景工作者流程是正确的方法,你只需要消除所有&#34;交叉线程操作&#34;通过确保修改表单元素的所有调用都使用Control.Invoke
方法包装器来实现异常。
答案 2 :(得分:0)
如果要使用backgroundworker / multithreading,可以使用委托更新表单(它们在ui线程上运行)。请参阅此处的示例:How to update the GUI from another thread in C#?
答案 3 :(得分:0)
使用BackgroundWorker和RunWorkerAsync的简单示例。希望这会有所帮助。
public partial class Form2 : Form
{
BackgroundWorker worker = new BackgroundWorker();
public Form2()
{
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
InitializeComponent();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
int totalSteps = 5;
for (int i = 1; i <= totalSteps; i++)
{
Thread.Sleep(1000);
worker.ReportProgress(i);
}
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
resultText.Text = "Worker complete";
btnDoWork.Enabled = true;
progressBar1.Visible = false;
}
private void btnDoWork_Click(object sender, EventArgs e)
{
progressBar1.Visible = true;
worker.RunWorkerAsync();
}
}