2011-10-05 233 views
0

我尝试使用多线程处理一些数据,我使用线程池生成的线程数量等于核心数量(限于.NET 2.0至3.5,因此无法使用TPL)。从线程池c更新进度条#

我的所有线程执行相同的功能,在我的数据的不同部分操作。

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

我的代码看起来像

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

速度是最重要的,我如果跨线程调用占用最小的时间,所以会是非常有益的。 谢谢

+2

“使用线程池生成等于内核数量的线程” - 很少有人明确需要自行优化线程数。线程池是为你设计的。 –

回答

0

有一点你可以做更新用户控件,在你的情况进度条。 添加您的形式作为输入参数,或添加一些回调接口的结果,你的形式将实施:

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

下面是一个例子:

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

我的Algo和窗体属于不同的类。不能删除限制。 – user938972

+0

因此不能使用Invoke。任何解决方法? – user938972

+0

您的意思是说您没有直接访问ProgressBar控件,因为它在不同的表单上,并且线程池在另一个类中调用? – A9S6

0

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

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

请记住,在某些情况下(例如一个线程内循环使用该委托的距离),你可能需要声明一个委托并传递价值成其为一个参数。如果你不这样做,你可能会与当地人发生奇怪的行为。这也是使用匿名方法和Action类的情况。