2010-08-03 2 views
2

Честно говоря, я немного хромаю, когда дело доходит до потоковой обработки;) Поэтому я прошу немного помочь.Синхронизация подпотока с основной нитью - не такая очевидная проблема

Предположим, у нас есть какой-то контроль, на котором мы можем нарисовать некоторые диаграммы. Существует также метод, который рисует диаграмму этого элемента управления. Проблема заключается в том, что метод построения диаграмм имеет доступ только к одному из полей элемента управления, и нам нужно обновить элемент управления, когда график будет готов.

Итак, давайте предположим, наш контроль выглядит следующим образом:

class ChartingControl : System.Windows.Forms.Control 
{ 
    public Canvas canvas; 
    public void Refresh(); 
    /* 
    ... other fields/methods 
    */ 
} 

где Canvas класс используется для рисования изображения (что-то вроде графика).
Метод построения графиков имеет доступ только к canvas объекта (мы не можем изменить его), так что это выглядит так:

public static void DrawChart(canvas) 
{ /* draw */ } 

Этот метод может быть вызван из отдельной нити, фон рабочего и т.д. ... И я необходимо синхронизировать его с основным потоком и вызвать Refresh(), когда график готов.

Прямо сейчас, когда график будет готов, я установить флаг на холсте объект

public static void DrawChart(canvas) 
{ /* draw */ 
    canvas.Tag = true; // chart is ready 
} 

И у меня есть фон работник работает внутри графиков контроля и прослушивания, если canvas.Tag поле изменилось, и если да, то он вызывает Refresh()

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

Ограничения:
- мы не можем изменить Canvas класс. Единственное, что мы можем использовать это Tag поле (типа object
- мы можем изменить ChartingControl класс и метод рисования
. - Там может быть много графиков управления
. - Мы не имеем никакого контроля над тем, как DrawChart называется Он может вызываться в отдельном потоке, или нет. это называется в другом месте. Все, что мы можем сделать, это создать элемент управления и метод DrawChart и попытаться общаются их как-то

Решение
ОК, я решил это так : in ChartingControl Я создал ManualResetEvent manualReset и работника фона.

задний рабочий ждет manualReset:

void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
    { 
      manualReset.WaitOne(); // Wait for a chart to be ready 
    } 

и в конце концов вызывает метод Reset()

void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) 
    { 
     Refresh(); 
    } 

я передать manualReset объект внутри canvas.Tag и внутри метода рисования, когда диаграмма готов я звоню manualReset.Set();, чтобы передать сигнал, что график готов.

+0

Метод DrawChart начинает новую тему или вы называете это в другом потоке? –

+0

Я называю это в другом потоке – Gacek

ответ

1

Хорошо, я решил это так: в ChartingControl Я создал ManualResetEvent manualReset и работника фона.

задний рабочий ждет manualReset:

void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
    { 
      manualReset.WaitOne(); // Wait for a chart to be ready 
    } 

и в конце концов вызывает метод Reset()

void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) 
    { 
     Refresh(); 
    } 

я передать manualReset объект внутри canvas.Tag и внутри метода рисования, когда диаграмма готов я звоню manualReset.Set();, чтобы передать сигнал, что график готов.

+0

Вы сделали правильный выбор ИМО - можете ли вы обновить свой ОП, а не публиковать ответ на свой собственный пост, хотя это упрощает просмотр проблемы и решения в одном месте – zebrabox

0

Предположив вы имеете дело с синхронизацией доступа к объекту Canvas, я просто рекомендую вам сделать
myChartingControl.Invoke(new Action(myChartingControl.Refresh));
из другого потока, который рисует график

+0

Из потока, который рисует диаграмму, у меня нет доступа к элементу управления диаграммами:/ – Gacek

+0

, но вы каким-то образом передаете ссылку на холст, не так ли? Это означает, что вы можете передать ссылку на элемент управления и взять из него холст – ULysses

+0

Я создаю библиотеку, которая используется в другом месте. Элемент управления содержит объект Canvas и в приложении, в котором он используется, создается новый элемент управления, а затем вызывается «DrawChart (chartingControl.canvas)» (прямо или в подпотоке) – Gacek

0

BackgroundWorker поможет вам

void StartDrawChart(){ 

     BackgroundWorker bw = new BackgroundWorker(); 
     bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
     bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted); 
     bw.RunWorkerAsync() 
    } 


    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     this.Refresh(); 
    } 

    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     DrawChart(this.canvas); 
    } 
+0

Да, это было бы решением, если бы я мог контролировать, как вызывается метод DrawChart. Но он используется в другом месте, и я не контролирую его. Я уточню свой вопрос. – Gacek

Смежные вопросы