【问题标题】:c# delegate progressbar multithread and class in classc# 委托进度条多线程和类中的类
【发布时间】:2014-12-17 09:27:06
【问题描述】:

我的 Winform(Class A) 使用 Class B 和 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 机器上运行。

【问题讨论】:

  • 在 .NET 4.5 中,您可以使用 Progress 类将进度消息从后台线程发送到 UI 线程,从而避免 Invoke 耦合与窗体的背景类。您使用的是哪个 .NET 版本?
  • 我使用的是 .NET 4.0,因为它必须在 Windows XP 机器上运行。
  • 只要你有VS 2012+,你可以添加Microsoft.Bcl.Async Nuget包来获得async/awaitProgress的支持。既然 VS 2013 Pro 是免费的,这应该不是问题
  • 谢谢!我会调查一下,目前使用的是 VS2012。所以应该是可以的。
  • 添加了一个示例作为答案

标签: c# multithreading winforms delegates


【解决方案1】:

在带有Microsoft.Bcl.Async 包的.NET 4.5 或.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&lt;int&gt; 而不是Progress&lt;Tuple&lt;int,string&gt;&gt;,但这表明 Progress 对象可以将复杂对象作为消息发送,而不仅仅是一个整数。

Progress 作为IProgress 接口传递是强制性的,因为Progress 显式实现了IProgress.Report。这样,即使您想懒惰地将Progress 传递给工作人员,您也无法获得对特定实现的依赖

【讨论】:

  • 非常感谢!正是我需要的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-21
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
相关资源
最近更新 更多