我得到了使用B类和B类的Winform(A类) B类使用C类
C类为我做的事情是读取word文档并检索数据并将其粘贴到excel文件中。 我为此做了一个单独的线程,所以我仍然可以移动winform。
现在我希望我的进度条能够查看它正在处理的文件的值,从0到amountoffiles。
只有在表单为活动窗口时才会更新。
我目前在C组中得到了这个。我将progressBar作为参数从A类到B到C。
private void SetValue(int value)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
try
{
if (this.pbar.InvokeRequired)
{
if (Doc_converter.Form1.ActiveForm != null)
{
SetTextCallback d = new SetTextCallback(SetValue);
Doc_converter.Form1.ActiveForm.Invoke(d, new object[] { value });
}
}
else
{
this.pbar.Value = value;
}
}
catch
{
//To do
}
}
delegate void SetTextCallback(int value);
有没有不同的方法来完成这项工作?
或从C级到A级的代表?
请记住,它与表单线程不同。
编辑:忘记提到我只能使用.NET 4.0或更低版本,因为应用程序必须在Windows XP机器上运行。
答案 0 :(得分:0)
在.NET 4.5或带有Microsoft.Bcl.Async包的.NET 4.0中,您可以使用Progress类将进度消息(实际上是完整的对象)从一个线程发送到另一个线程。在创建初始Progress对象的线程上(特别是在发生对象创建的SynchronizationContext上)引发事件,因此您根本不需要使用Invoke
。
您应该在UI线程上创建一个Progress对象,并将其作为IProgress
接口传递给后台处理类。每次后台线程调用Report
时,将在表单中调用相应的回调,例如:
在表格上:
private void ReportProgress(Tuple<int,string> progress)
{
pbar.Value=progress.Item1;
status.Text=progress.Item2;
}
public void StartProcessing()
{
IProgress<Tuple<int,string>> progress=new Progress<Tuple<int,string>>(ReportProgress);
var workerClass=new MyWorkerClass();
workerClass.DoWork(progress);
....
}
在工人阶级:
public void DoWork(IProgress<Tuple<int,string> progress)
{
for (int i=0;i++;i<1000)
{
if (i%10==0)
{
progress.Report(Tuple.Create(i/10,String.Format("Now at {0}",i);
}
}
}
这个例子当然是人为的,我可以使用Progress<int>
代替Progress<Tuple<int,string>>
,但这表明Progress对象可以将复杂对象作为消息发送,而不仅仅是整数。
将Progress
作为IProgress
接口传递是必需的,因为Progress
明确实现了IProgress.Report
。通过这种方式,即使您想懒惰地将Progress
传递给工作人员,也无法依赖于特定的实现