Обновление индикатора выполнения из пула потоков c # - PullRequest
0 голосов
/ 05 октября 2011

Я пытаюсь обработать некоторые данные, используя многопоточность, где я использую пул потоков, чтобы генерировать потоки, равные количеству ядер (ограничено .NET 2.0 до 3.5, поэтому я не могу использовать TPL).

Все мои потоки выполняют одну и ту же функцию, работая в разных частях моих данных.

Моя проблема в том, что я не могу обновить индикатор выполнения из потоков пула потоков. Найдены такие решения, как invoke и Background worker, но я не могу понять, как их использовать, помогите мне, как их использовать.

мой код выглядит как

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

Скорость имеет для меня первостепенное значение, поэтому было бы очень полезно, если бы вызов с несколькими потоками занимал минимальное время. Спасибо

Ответы [ 3 ]

1 голос
/ 05 октября 2011

Вот пример:

ThreadPool.QueueUserWorkItem(new WaitCallback(o =>
    {
        // worker method implementation
        .....
        progressBar1.Invoke(new MethodInvoker(() => progressBar1.Value = 20));
    }));
0 голосов
/ 05 октября 2011

Стандартный вызов, вероятно, самый простой, и вы можете использовать анонимный делегат, чтобы сделать его чище.

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

Имейте в виду, что в определенных сценариях (например, циклическое использование этого делегата из одного потока) вам может потребоваться объявить делегат и передать значение в него в качестве параметра. Если вы этого не сделаете, вы можете получить странное поведение с местными жителями. Это касается использования анонимных методов и класса Action.

0 голосов
/ 05 октября 2011

Есть немного, что вы можете сделать с обновлением пользовательских элементов управления, в вашем случае индикатор выполнения.Добавьте вашу форму в качестве входного параметра или добавьте некоторый интерфейс обратного вызова для результатов, которые будет реализовывать ваша форма:

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