Не секрет что время от времени приходится кодировать достаточно длительные операции. Реализация таких операций напрямую в обработчике пользователя ведёт к блокированию пользовательского интерфейса. Соответственно логично запускать подобные действия в отдельном потоке (нитке). При этом с особым пиететом надо относится к взаимодействию данного процесса с элементами пользователького интерфейса. Дело в том что элементы пользовательского интерфейса потоконебезопасны и доступ к ним надо синхронизировать. Ниже приведён достаточно элегантный вариант реализации подобного взаимодействия. Основное "волшебство" находится в строчках 58-76. Новый поток образуется посредством вызова метода
(стр. 75) у
(стр 64-74). Для взаимодействия с элементами пользовательского интерфейса используется
.
(стр 72 и 74), выполняющего в свою очередь анонимные делегаты в потоке UI...
1 using System;
2 using System.Drawing;
3 using System.Threading;
4 using System.Windows.Forms;
5
6 public class AsyncExecutionDemoForm : Form
7 { 8 private Button startButton;
9 private ProgressBar progressBar;
10
11 public AsyncExecutionDemoForm()
12 { 13 createUI();
14 }
15
16 private void createUI()
17 { 18 startButton = new Button();
19 progressBar = new ProgressBar();
20 SuspendLayout();
21 //
22 // startButton
23 //
24 startButton.Anchor = ((AnchorStyles.Top | AnchorStyles.Bottom)
25 | AnchorStyles.Left)
26 | AnchorStyles.Right;
27 startButton.Location = new Point(168, 50);
28 startButton.Name = "startButton";
29 startButton.Size = new Size(127, 23);
30 startButton.TabIndex = 0;
31 startButton.Text = "Поехали!";
32 startButton.UseVisualStyleBackColor = true;
33 startButton.Click += new EventHandler(startButton_Click);
34 //
35 // progressBar
36 //
37 progressBar.Anchor = (AnchorStyles.Top | AnchorStyles.Left)
38 | AnchorStyles.Right;
39 progressBar.Location = new Point(8, 12);
40 progressBar.Name = "progressBar";
41 progressBar.Size = new Size(447, 23);
42 progressBar.TabIndex = 1;
43 progressBar.Style = ProgressBarStyle.Continuous;
44 //
45 // AsyncExecutionDemoForm
46 //
47 AutoScaleDimensions = new SizeF(6F, 13F);
48 AutoScaleMode = AutoScaleMode.Font;
49 ClientSize = new Size(468, 88);
50 Controls.Add(progressBar);
51 Controls.Add(startButton);
52 Name = "AsyncExecutionDemoForm";
53 Text = "AsyncExecutionDemoForm";
54 ResumeLayout(false);
55 }
56
57
58 void startButton_Click(object sender, EventArgs e)
59 { 60 SynchronizationContext sc = SynchronizationContext.Current;
61 // Заблокируем кнопку
62 startButton.Enabled = false;
63 ((SendOrPostCallback)
64 delegate(object delay)
65 { 66 // Что-то делаем
67 for (int i = 0; i < 100; ++i)
68 { 69 // Имитируем бурную деятельность
70 Thread.Sleep((int) delay);
71 // Обновляем UI в правильном потоке
72 sc.Send(delegate { progressBar.Value = i + 1; }, null); 73 }
74 sc.Send(delegate { startButton.Enabled = true; }, null); 75 }).BeginInvoke(100, null, null);
76 }
77
78
79 [STAThread]
80 static void Main()
81 { 82 Application.EnableVisualStyles();
83 Application.SetCompatibleTextRenderingDefault(false);
84 Application.Run(new AsyncExecutionDemoForm());
85 }
86 }