简体   繁体   English

从线程池C#更新进度条

[英]Updating progress bar from a threadpool c#

I have trying to process some data using multithreading where I am using threadpool to generate threads equal to the number of cores(Limited to .NET 2.0 to 3.5 so cant use TPL). 我试图使用多线程处理一些数据,其中我正在使用线程池生成等于内核数的线程(限于.NET 2.0到3.5,因此不能使用TPL)。

All my threads execute the same function operating in different parts of my data. 我所有的线程在数据的不同部分执行相同的功能。

My problem is I am unable to update the progress bar from the threads of the threadpool. 我的问题是我无法从线程池的线程更新进度栏。 Found solutions such as invoke and Background worker but could not really understand how to use them please help me out how to use them. 找到了诸如invoke和Background worker之类的解决方案,但无法真正理解如何使用它们,请帮助我了解如何使用它们。

my code looks like 我的代码看起来像

 private static float[] inpdat=new float[1000];//The input array to process
 //The spawned threads
 public void dowork(object o) 
 {
    int np = (int)o;
    for(int i=np;i<inpdat.length;i=i+Environment.ProcessorCount)
    {
         //do some processing
         if(np==0)
          {
              //update progress bar here
          }
    }
 }


    //The main thread
    for (int npou = 0; npou < numproc; npou++)
    {
        resetEvents[npou] = new ManualResetEvent(false);
        ThreadPool.QueueUserWorkItem(new WaitCallback(dowork), npou);
        PetrelLogger.InfoOutputWindow("manual reset event set");
    }

Speed is of paramount importance to me so would be very helpful if the cross thread calling takes up minimum time. 速度对我而言至关重要,因此如果跨线程调用占用最少的时间,它将非常有帮助。 Thanks 谢谢

Here is an example: 这是一个例子:

ThreadPool.QueueUserWorkItem(new WaitCallback(o =>
    {
        // worker method implementation
        .....
        progressBar1.Invoke(new MethodInvoker(() => progressBar1.Value = 20));
    }));

There is a little you can do with updating user controls, in your case Progress bar. 在进度栏中,您可以做一些更新用户控件的事情。 Add your form as the input parameter, or add some callback interface for the results, that your form will implement: 将您的表单添加为输入参数,或者为结果添加一些回调接口,您的表单将实现该表单:

interface IMyCallback
{
    void Progress(int progress);
}

In form implementation add following code: 在表单实现中,添加以下代码:

void Progress(int Progress)
{
    if(this.InvokeRequired)
    {
        this.BeginInvoke(new ParametrizedThreadStart(Inv_Progress), Progress);
    }
    else
    {
        Inv_Progress(Progress);
    }
}

void Inv_Progress(object obj)
{
    int progress = obj as int;
    // do your update progress bar work here

}

Now you can do following: 现在您可以执行以下操作:

public void dowork(object o) 
 {
    int np = (int)o;
    for(int i=np;i<inpdat.length;i=i+Environment.ProcessorCount)
    {
         //do some processing
         if(np==0)
          {
              myCallback.Progress(0);
          }
    }
 }

A standard invoke is probably easiest, and you can use an anonymous delegate to make it cleaner. 标准调用可能是最简单的,并且您可以使用匿名委托使其更整洁。

int n = 5;
myProgressBar.Invoke(
    delegate
    {
        myProgressBar.Value = n;
    }
);

Keep in mind that in certain scenarios (eg looped use of this delegate from within one thread) you may need to declare a delegate and pass the value into it as a parameter. 请记住,在某些情况下(例如,从一个线程内循环使用此委托),您可能需要声明一个委托并将值作为参数传递给它。 If you don't, you can get strange behaviour with locals. 如果不这样做,您可能会与当地人发生奇怪的行为。 This is the case for use of anonymous methods and the Action class, too. 使用匿名方法和Action类也是如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM