пятница, 6 января 2012 г.

UI и многопоточность

Продолжаем осваивать .NET и многопоточность в C#. Очень часто возникает ситуация, когда из вторичных потоков необходимо изменить состояние пользовательского интерфейса, прогрессбары, кнопки и прочее. Для решение подобных вопросов можно использовать контекст свободных потоков SynchronizationContext. В него сохраняется поток UI. А дальше просходит вызов метода Send для выполнения переданного в качестве параметра делегата в потоке UI вот так:

uiContext.Send(d => progressBar.Value = i, null);

Вот пример кода, взято отсюда:

public partial class MainWindow : Window

{

SynchronizationContext uiContext;

Thread t;

public MainWindow()

{

InitializeComponent();

}

private void btnStart_Click(object sender, RoutedEventArgs e)

{

btnStart.IsEnabled = false;

btnStop.IsEnabled = true;

uiContext = SynchronizationContext.Current;

t = new Thread(Calc);

t.Start();

}

private void btnStop_Click(object sender, RoutedEventArgs e)

{

t.Interrupt();

}

private void Calc()

{

try

{

for (Int32 i = 0; i <= 100; i++)

{

uiContext.Send(d => progressBar.Value = i, null);

Thread.Sleep(100);

}

}

catch

{

}

finally

{

uiContext.Send(d => progressBar.Value = 0, null);

uiContext.Send(d => btnStop.IsEnabled = false, null);

uiContext.Send(d => btnStart.IsEnabled = true, null);

}

}

private void Window_Closed(object sender, EventArgs e)

{

t.Interrupt();

}

}

Комментариев нет: