从线程池c#更新进度条

发布于 2024-12-08 09:27:38 字数 901 浏览 0 评论 0原文

我尝试使用多线程处理一些数据,其中我使用线程池生成等于内核数量的线程(仅限.NET 2.0 到 3.5,因此无法使用 TPL)。

我的所有线程都在数据的不同部分执行相同的函数。

我的问题是我无法从线程池的线程更新进度条。找到了诸如调用和后台工作程序之类的解决方案,但无法真正理解如何使用它们,请帮助我了解如何使用它们。

我的代码看起来

 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");
    }

速度对我来说是最重要的,所以如果跨线程调用占用最少的时间将会非常有帮助。 谢谢

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).

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

单挑你×的.吻 2024-12-15 09:27:39

您可以通过更新用户控件(在您的情况下进度栏)来执行一些操作。
添加您的表单作为输入参数,或者为您的表单将实现的结果添加一些回调接口:

interface IMyCallback
{
    void Progress(int progress);
}

在表单实现中添加以下代码:

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

}

现在您可以执行以下操作:

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);
          }
    }
 }

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);
          }
    }
 }
唔猫 2024-12-15 09:27:39

标准调用可能是最简单的,您可以使用匿名委托来使其更简洁。

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

请记住,在某些情况下(例如,从一个线程内循环使用此委托),您可能需要声明一个委托并将值作为参数传递给它。如果不这样做,当地人可能会做出奇怪的行为。使用匿名方法和 Action 类也是如此。

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 (e.g. 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.

孤千羽 2024-12-15 09:27:38

这是一个例子:

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

Here is an example:

ThreadPool.QueueUserWorkItem(new WaitCallback(o =>
    {
        // worker method implementation
        .....
        progressBar1.Invoke(new MethodInvoker(() => progressBar1.Value = 20));
    }));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文