Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
1

Как правильно работать с SynchronizationContext?

15.03.2013, 11:52. Показов 15145. Ответов 20
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Собственно искал толковые примеры, где было бы понятно для чего вообще нужен этот класс, но не нашёл ничего внятного. Может кто-то на примере объяснить, как оно работает и зачем нужно? Вроде бы BackgroundWorker его использует.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.03.2013, 11:52
Ответы с готовыми решениями:

Зачем нужен/как использовать SynchronizationContext.SetSynchronizationContext(.)?
Привет! Wpf приложение, в нем кнопка, которая выполняет такой код: private async void...

Как правильно работать с БД
Visual Studio 2015 VB.NET 4.5.2 + SQL Подскажите плиз след. вопрос: Есть у меня допустим...

Как правильно работать с My.Settings?
Как правильно работать с My.Settings? У меня не получается сохранить и прочитать значение флажка...

Как правильно работать с Recordset
Здравствуйте. Сейчас данные получаю так: SQLText = "select t.znach from chasspt t where...

20
197 / 197 / 5
Регистрация: 24.07.2010
Сообщений: 1,311
15.03.2013, 12:00 2
собсно вбил в гугле название этого класса и вот сразу выпала статья http://habrahabr.ru/post/107583/
0
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
15.03.2013, 12:03  [ТС] 3
Я находил это. Пример оттуда не работает.
0
1453 / 845 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
15.03.2013, 12:03 4
Цитата Сообщение от 23Alex24 Посмотреть сообщение
собсно вбил в гугле название этого класса и вот сразу выпала статья
Раздел Взаимодействие с gui-потоками в .Net Framework
0
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
15.03.2013, 12:04  [ТС] 5
Да и там async, await. Мне это не нужно, я хочу понять саму суть работы этого класса без лишних заморочей с async, await
0
1453 / 845 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
15.03.2013, 12:04 6
Цитата Сообщение от Casper-SC Посмотреть сообщение
Я находил это. Пример оттуда не работает
Это на .NET 4.5 расчитано!
1
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
15.03.2013, 12:07  [ТС] 7
Чёт я не совсем врубаюсь в этот код. Вроде и понятно, когда точек останова наставишь, но всё же. Я чёт подзабыл, что там делает async, await и сейчас читать не охота про это. Но видимо придётся...
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using System;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
 
namespace ConsoleApplication1
{
    class MyContext : SynchronizationContext
    {
        public override void Post(SendOrPostCallback d, object state)
        {
            Console.WriteLine("MyContext.Post");
            base.Post(d, state);
        }
 
        public override void Send(SendOrPostCallback d, object state)
        {
            Console.WriteLine("MyContext.Send");
            base.Send(d, state);
        }
    }
 
    class Program
    {
        static async Task SavePage(string file, string a)
        {
            using (var stream = File.AppendText(file))
            {
                var html = await new WebClient().DownloadStringTaskAsync(a);
                await stream.WriteAsync(html);
            }
        }
 
        static void Main(string[] args)
        {
            SynchronizationContext.SetSynchronizationContext(new MyContext());
            var task = SavePage("habrahabr", "http://habrahabr.ru");
            task.Wait();
        }
    }
}
0
1453 / 845 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
15.03.2013, 12:13 8
Вот тут если почитать можно понять: http://www.codeproject.com/Art... ext-Part-I

Грубо говоря этот класс использовали как Dispatcher из WPF.

Добавлено через 1 минуту
вот тут:

Кликните здесь для просмотра всего текста


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
 
    private void mToolStripButtonThreads_Click(object sender, EventArgs e)
    {
        // let's see the thread id
        int id = Thread.CurrentThread.ManagedThreadId;
        Trace.WriteLine("mToolStripButtonThreads_Click thread: " + id);
 
        // grab the sync context associated to this
        // thread (the UI thread), and save it in uiContext
        // note that this context is set by the UI thread
        // during Form creation (outside of your control)
        // also note, that not every thread has a sync context attached to it.
        SynchronizationContext uiContext = SynchronizationContext.Current;
 
        // create a thread and associate it to the run method
        Thread thread = new Thread(Run);
 
        // start the thread, and pass it the UI context,
        // so this thread will be able to update the UI
        // from within the thread
        thread.Start(uiContext);
    }
 
    private void Run(object state)
    {
        // lets see the thread id
        int id = Thread.CurrentThread.ManagedThreadId;
        Trace.WriteLine("Run thread: " + id);
 
        // grab the context from the state
        SynchronizationContext uiContext = state as SynchronizationContext;
 
        for (int i = 0; i < 1000; i++)
        {
            // normally you would do some code here
            // to grab items from the database. or some long
            // computation
            Thread.Sleep(10);
 
            // use the ui context to execute the UpdateUI method,
            // this insure that the UpdateUI method will run on the UI thread.
 
            uiContext.Post(UpdateUI, "line " + i.ToString());
        }
    }
 
    /// <summary>
    /// This method is executed on the main UI thread.
    /// </summary>
    private void UpdateUI(object state)
    {
        int id = Thread.CurrentThread.ManagedThreadId;
        Trace.WriteLine("UpdateUI thread:" + id);
        string text = state as string;
        mListBox.Items.Add(text);
    }
}


Добавлено через 2 минуты
Короче говоря создаёшь его в одном потоке и передаешь в другой. Ну и из второго потока можно выполнить код какбы в первом потоке.

Добавлено через 1 минуту
Ну а если зайти ещё дальше то таким образом можно создать один такой контекст и передать в кучу потоков. И они смогут через него закидывать расчитанные данные в основной поток.
1
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
15.03.2013, 12:19  [ТС] 9
Цитата Сообщение от LeniumSoft Посмотреть сообщение
Короче говоря создаёшь его в одном потоке и передаешь в другой. Ну и из второго потока можно выполнить код какбы в первом потоке.
То есть, гурбо говоря, можно замутить свой BackroundWorker и при инициации события какого-то можно из другого потока передавать данные в основной так, что подписчику на мой BackroundWorker не придётся вызывать Invoke или обращаться к Dispatcher (WinForms, WPF), чтобы выполнить код в обработчике события класса BackroundWorker?

Добавлено через 5 минут
Походу я замудрённо написал . Меня не поняли.
0
1453 / 845 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
15.03.2013, 12:24 10
Не! Я понял! Я коды вытаскиваю! Дабы проилюстрировать!

Весь BackgroundWorker
Кликните здесь для просмотра всего текста


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// Type: System.ComponentModel.BackgroundWorker
// Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll
 
using System;
using System.Runtime;
using System.Security.Permissions;
using System.Threading;
 
namespace System.ComponentModel
{
  [SRDescription("BackgroundWorker_Desc")]
  [DefaultEvent("DoWork")]
  [HostProtection(SecurityAction.LinkDemand, SharedState = true)]
  public class BackgroundWorker : Component
  {
    private static readonly object doWorkKey = new object();
    private static readonly object runWorkerCompletedKey = new object();
    private static readonly object progressChangedKey = new object();
    private bool canCancelWorker;
    private bool workerReportsProgress;
    private bool cancellationPending;
    private bool isRunning;
    private AsyncOperation asyncOperation;
    private readonly BackgroundWorker.WorkerThreadStartDelegate threadStart;
    private readonly SendOrPostCallback operationCompleted;
    private readonly SendOrPostCallback progressReporter;
 
    [Browsable(false)]
    [SRDescription("BackgroundWorker_CancellationPending")]
    public bool CancellationPending
    {
      [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get
      {
        return this.cancellationPending;
      }
    }
 
    [SRDescription("BackgroundWorker_IsBusy")]
    [Browsable(false)]
    public bool IsBusy
    {
      [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get
      {
        return this.isRunning;
      }
    }
 
    [SRCategory("PropertyCategoryAsynchronous")]
    [DefaultValue(false)]
    [SRDescription("BackgroundWorker_WorkerReportsProgress")]
    public bool WorkerReportsProgress
    {
      [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get
      {
        return this.workerReportsProgress;
      }
      [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] set
      {
        this.workerReportsProgress = value;
      }
    }
 
    [SRCategory("PropertyCategoryAsynchronous")]
    [DefaultValue(false)]
    [SRDescription("BackgroundWorker_WorkerSupportsCancellation")]
    public bool WorkerSupportsCancellation
    {
      [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get
      {
        return this.canCancelWorker;
      }
      [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] set
      {
        this.canCancelWorker = value;
      }
    }
 
    [SRCategory("PropertyCategoryAsynchronous")]
    [SRDescription("BackgroundWorker_DoWork")]
    public event DoWorkEventHandler DoWork
    {
      add
      {
        this.Events.AddHandler(BackgroundWorker.doWorkKey, (Delegate) value);
      }
      remove
      {
        this.Events.RemoveHandler(BackgroundWorker.doWorkKey, (Delegate) value);
      }
    }
 
    [SRDescription("BackgroundWorker_ProgressChanged")]
    [SRCategory("PropertyCategoryAsynchronous")]
    public event ProgressChangedEventHandler ProgressChanged
    {
      add
      {
        this.Events.AddHandler(BackgroundWorker.progressChangedKey, (Delegate) value);
      }
      remove
      {
        this.Events.RemoveHandler(BackgroundWorker.progressChangedKey, (Delegate) value);
      }
    }
 
    [SRCategory("PropertyCategoryAsynchronous")]
    [SRDescription("BackgroundWorker_RunWorkerCompleted")]
    public event RunWorkerCompletedEventHandler RunWorkerCompleted
    {
      add
      {
        this.Events.AddHandler(BackgroundWorker.runWorkerCompletedKey, (Delegate) value);
      }
      remove
      {
        this.Events.RemoveHandler(BackgroundWorker.runWorkerCompletedKey, (Delegate) value);
      }
    }
 
    static BackgroundWorker()
    {
    }
 
    public BackgroundWorker()
    {
      this.threadStart = new BackgroundWorker.WorkerThreadStartDelegate(this.WorkerThreadStart);
      this.operationCompleted = new SendOrPostCallback(this.AsyncOperationCompleted);
      this.progressReporter = new SendOrPostCallback(this.ProgressReporter);
    }
 
    public void CancelAsync()
    {
      if (!this.WorkerSupportsCancellation)
        throw new InvalidOperationException(SR.GetString("BackgroundWorker_WorkerDoesntSupportCancellation"));
      this.cancellationPending = true;
    }
 
    protected virtual void OnDoWork(DoWorkEventArgs e)
    {
      DoWorkEventHandler workEventHandler = (DoWorkEventHandler) this.Events[BackgroundWorker.doWorkKey];
      if (workEventHandler == null)
        return;
      workEventHandler((object) this, e);
    }
 
    protected virtual void OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
    {
      RunWorkerCompletedEventHandler completedEventHandler = (RunWorkerCompletedEventHandler) this.Events[BackgroundWorker.runWorkerCompletedKey];
      if (completedEventHandler == null)
        return;
      completedEventHandler((object) this, e);
    }
 
    protected virtual void OnProgressChanged(ProgressChangedEventArgs e)
    {
      ProgressChangedEventHandler changedEventHandler = (ProgressChangedEventHandler) this.Events[BackgroundWorker.progressChangedKey];
      if (changedEventHandler == null)
        return;
      changedEventHandler((object) this, e);
    }
 
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    public void ReportProgress(int percentProgress)
    {
      this.ReportProgress(percentProgress, (object) null);
    }
 
    public void ReportProgress(int percentProgress, object userState)
    {
      if (!this.WorkerReportsProgress)
        throw new InvalidOperationException(SR.GetString("BackgroundWorker_WorkerDoesntReportProgress"));
      ProgressChangedEventArgs changedEventArgs = new ProgressChangedEventArgs(percentProgress, userState);
      if (this.asyncOperation != null)
        this.asyncOperation.Post(this.progressReporter, (object) changedEventArgs);
      else
        this.progressReporter((object) changedEventArgs);
    }
 
    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    public void RunWorkerAsync()
    {
      this.RunWorkerAsync((object) null);
    }
 
    public void RunWorkerAsync(object argument)
    {
      if (this.isRunning)
        throw new InvalidOperationException(SR.GetString("BackgroundWorker_WorkerAlreadyRunning"));
      this.isRunning = true;
      this.cancellationPending = false;
      this.asyncOperation = AsyncOperationManager.CreateOperation((object) null);
      this.threadStart.BeginInvoke(argument, (AsyncCallback) null, (object) null);
    }
 
    private void AsyncOperationCompleted(object arg)
    {
      this.isRunning = false;
      this.cancellationPending = false;
      this.OnRunWorkerCompleted((RunWorkerCompletedEventArgs) arg);
    }
 
    private void ProgressReporter(object arg)
    {
      this.OnProgressChanged((ProgressChangedEventArgs) arg);
    }
 
    private void WorkerThreadStart(object argument)
    {
      object result = (object) null;
      Exception error = (Exception) null;
      bool cancelled = false;
      try
      {
        DoWorkEventArgs e = new DoWorkEventArgs(argument);
        this.OnDoWork(e);
        if (e.Cancel)
          cancelled = true;
        else
          result = e.Result;
      }
      catch (Exception ex)
      {
        error = ex;
      }
      this.asyncOperation.PostOperationCompleted(this.operationCompleted, (object) new RunWorkerCompletedEventArgs(result, error, cancelled));
    }
 
    private delegate void WorkerThreadStartDelegate(object argument);
  }
}


C#
1
2
3
4
5
6
7
8
9
10
public void ReportProgress(int percentProgress, object userState)
    {
      if (!this.WorkerReportsProgress)
        throw new InvalidOperationException(SR.GetString("BackgroundWorker_WorkerDoesntReportProgress"));
      ProgressChangedEventArgs changedEventArgs = new ProgressChangedEventArgs(percentProgress, userState);
      if (this.asyncOperation != null)
        this.asyncOperation.Post(this.progressReporter, (object) changedEventArgs);
      else
        this.progressReporter((object) changedEventArgs);
    }
this.asyncOperation.Post(this.progressReporter, (object) changedEventArgs)

private AsyncOperation asyncOperation;

Код AsyncOperation

Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Type: System.ComponentModel.AsyncOperation
// Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll
 
using System;
using System.Runtime;
using System.Security.Permissions;
using System.Threading;
 
namespace System.ComponentModel
{
  [HostProtection(SecurityAction.LinkDemand, SharedState = true)]
  public sealed class AsyncOperation
  {
    private SynchronizationContext syncContext;
    private object userSuppliedState;
    private bool alreadyCompleted;
 
    public object UserSuppliedState
    {
      [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get
      {
        return this.userSuppliedState;
      }
    }
 
    public SynchronizationContext SynchronizationContext
    {
      [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get
      {
        return this.syncContext;
      }
    }
 
    private AsyncOperation(object userSuppliedState, SynchronizationContext syncContext)
    {
      this.userSuppliedState = userSuppliedState;
      this.syncContext = syncContext;
      this.alreadyCompleted = false;
      this.syncContext.OperationStarted();
    }
 
    ~AsyncOperation()
    {
      if (this.alreadyCompleted || this.syncContext == null)
        return;
      this.syncContext.OperationCompleted();
    }
 
    public void Post(SendOrPostCallback d, object arg)
    {
      this.VerifyNotCompleted();
      this.VerifyDelegateNotNull(d);
      this.syncContext.Post(d, arg);
    }
 
    public void PostOperationCompleted(SendOrPostCallback d, object arg)
    {
      this.Post(d, arg);
      this.OperationCompletedCore();
    }
 
    public void OperationCompleted()
    {
      this.VerifyNotCompleted();
      this.OperationCompletedCore();
    }
 
    internal static AsyncOperation CreateOperation(object userSuppliedState, SynchronizationContext syncContext)
    {
      return new AsyncOperation(userSuppliedState, syncContext);
    }
 
    private void OperationCompletedCore()
    {
      try
      {
        this.syncContext.OperationCompleted();
      }
      finally
      {
        this.alreadyCompleted = true;
        GC.SuppressFinalize((object) this);
      }
    }
 
    private void VerifyNotCompleted()
    {
      if (this.alreadyCompleted)
        throw new InvalidOperationException(SR.GetString("Async_OperationAlreadyCompleted"));
    }
 
    private void VerifyDelegateNotNull(SendOrPostCallback d)
    {
      if (d == null)
        throw new ArgumentNullException(SR.GetString("Async_NullDelegate"), "d");
    }
  }
}


Как можно видеть BackgroundWorker использует эту штуку для передачи прогресса выполнения в вызывающий поток!
1
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
15.03.2013, 12:28  [ТС] 11
Ну тут без поллитра не разобраться . Я видел эти исходники, их легко выдёргивает ReSharper.
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
15.03.2013, 12:43 12
его не только фоновый воркер использует, но и другие классы у которых есть асинхронные операции, webclient тот же

ну а так да - нужен для вброса в основной поток
создается через AsyncOperationManager.CreateOperation(), потом собственно вызывается его post..
0
1453 / 845 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
15.03.2013, 12:49 13
Цитата Сообщение от Casper-SC Посмотреть сообщение
Ну тут без поллитра не разобраться
Ну почему ж!!!! Смотри!

BackgroundWorker доржит в себе обёртку над SynchronizationContext.

Запускает расчёты в паралельном потоке. Паралельный поток считает и при этом сообщает сколько он уже просчитал. А BackgroundWorker через обёртку дёргает свои эвенты. Получается паралельный поток сообщает свой прогресс и если эти данные передать сразу, то в твоём коде вылетит ошибка. Поэтому this.asyncOperation.Post(this.progressReporter, (object) changedEventArgs);
переводит эти данные в основной поток.
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
15.03.2013, 12:53 14
во нашел руководство по использованию всей этой асинхронной радости http://msdn.microsoft.com/ru-r... 3kx67.aspx
возня страшная, но зато потом очень прикольно пользоваться )
0
1453 / 845 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
15.03.2013, 13:15 15
Цитата Сообщение от m0nax Посмотреть сообщение
во нашел руководство по использованию всей этой асинхронной радости
Перечитав всё это вслух можно вызвать дьявола!!!! Это описание путает мне мозг окончательно!
1
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
25.03.2013, 19:38  [ТС] 16
Почему на консоль не выводится сообщение? Что не правильно?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using System;
using System.Threading;
 
namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
            SynchronizationContext _sycnContext = SynchronizationContext.Current;
 
            LightEvent le = new LightEvent(_sycnContext);
            le.SomethingEvent += (sender, eventArgs) => Console.WriteLine("Сработало");
            le.DoWork();
 
            Console.ReadKey();
        }
    }
 
    internal class LightEvent
    {
 
        private SynchronizationContext _sycnContext;
 
        public LightEvent(SynchronizationContext uiContext)
        {
            _sycnContext = uiContext;
        }
 
        public event EventHandler SomethingEvent;
 
        public void StartOperation(object o)
        {
            _sycnContext.Post(OnEvent, null);
        }
 
        private void OnEvent(object state)
        {
            var handler = SomethingEvent;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }
 
        internal void DoWork()
        {
            ThreadPool.QueueUserWorkItem(StartOperation);
        }
    }
}
Добавлено через 8 минут
Хм... А вот на форме всё работает:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using System;
using System.Threading;
using System.Windows.Forms;
 
namespace WinForms_SyncContext
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
 
        private void MainForm_Load(object sender, EventArgs e)
        {
            SyncEvent le = new SyncEvent(SynchronizationContext.Current);
            le.SomethingEvent += (s, eventArgs) => labelInfo.Text = "Сработало!";
            le.DoWork();
        }
    }
 
    internal class SyncEvent
    {
        private readonly SynchronizationContext _sycnContext;
 
        public SyncEvent(SynchronizationContext uiContext)
        {
            _sycnContext = uiContext;
        }
 
        public event EventHandler SomethingEvent;
 
        public void StartOperation(object o)
        {
            _sycnContext.Post(OnEvent, null);
        }
 
        private void OnEvent(object state)
        {
            var handler = SomethingEvent;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }
 
        internal void DoWork()
        {
            ThreadPool.QueueUserWorkItem(StartOperation);
        }
    }
}
Почему же на консоли не работает? Я догадываюсь, что там как-то по другому нужно получать контекст синхронизации. Но как?
0
1453 / 845 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
26.03.2013, 11:17 17
Цитата Сообщение от Casper-SC Посмотреть сообщение
Но как?
Думаю просто нужно создать новый экземпляр и передать его в паралельный поток! Ведь он будет выполнять код в том потоке в котором он был создан!
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
26.03.2013, 12:14 18
Думаю, стоит пользоваться TPL
0
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
26.03.2013, 12:30  [ТС] 19
Цитата Сообщение от LeniumSoft Посмотреть сообщение
Думаю просто нужно создать новый экземпляр и передать его в паралельный поток! Ведь он будет выполнять код в том потоке в котором он был создан!
Собственно в первом примере я так и сделал. Всё так же не работает.

Цитата Сообщение от Psilon Посмотреть сообщение
Думаю, стоит пользоваться TPL
В смысле не заморачиваться такими вопросами или что? Я понял что речь о Task Parallel Library.
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
26.03.2013, 12:38 20
Casper-SC, да, не заморачиваться, и пользоваться стандартными классами типа parallel, запросов AsParallel() и так далее
0
26.03.2013, 12:38
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.03.2013, 12:38
Помогаю со студенческими работами здесь

Как правильно работать с JSON?
Здравствуйте! Подскажите, как правильно обрабатывать JSON в PHP, чтобы избежать монструозных...

Как правильно работать с RadioButton
подскажите, как правильно работать с RadioButton. моя программа не выдает ошибок, но работает...

Как правильно работать с парсером?
Читаю данную статью... http://habrahabr.ru/post/176635/ Все сделал... Предположим есть html...

Как правильно работать с vector?
// Create buttons. int const size = 5; int x = 50; int y = 50; int j = 0; vector&lt;Button*&gt;...

Как правильно работать с NRF24L01?
Доброго дня. Почему не сбрасывается прерывание на самом модуле? Как нужно правильно изначально...

Как правильно работать с потоками?
Есть richTextBox, в который записываются все действия, совершаемые программой. В процессе...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru