An instance of the Worker class in this example should be created in the UI stream, because in its constructor we get the synchronization context.
If you don’t want to push the synchronization context into a class that contains code that works in another thread, just SomeEventHandler Invoke method inside the handler method in the window class ( SomeEventHandler )
WPF and Windows Forms different SynchronizationContext implementations. That is, depending on the technology, it redirects execution in a different way to the UI flow (if we are talking about UI ).
Notice that without
_sycnContext = SynchronizationContext.Current ?? new SynchronizationContext();
The console application will not work, since SynchronizationContext.Current there will be null .
Worker.cs
using System; using System.Threading; namespace WorkerLib { public class Worker { private readonly SynchronizationContext _syncContext; public Worker() { _syncContext = SynchronizationContext.Current ?? new SynchronizationContext(); } public event EventHandler Started; public event EventHandler Completed; private void StartOperation(object state) { _syncContext.Post(OnStarted, null); // Делаем работу Thread.Sleep(1250); _syncContext.Post(OnCompleted, null); } public void DoWork() { ThreadPool.QueueUserWorkItem(StartOperation); } private void OnCompleted(object state) { var handler = Completed; if (handler != null) handler(this, EventArgs.Empty); } private void OnStarted(object state) { var handler = Started; if (handler != null) handler(this, EventArgs.Empty); } } }
Windows forms
MainForm.cs
using System; using System.Windows.Forms; using WorkerLib; namespace WinForms_SyncContextExample { public partial class MainForm : Form { private readonly Worker _worker; public MainForm() { InitializeComponent(); _worker = new Worker(); _worker.Started += (sender, args) => infoLabel.Text = "Запустили работу"; _worker.Completed += (sender, args) => infoLabel.Text = "Работа завершена"; } private void WorkButton_Click(object sender, EventArgs e) { _worker.DoWork(); } } }
Console
Program.cs
using System; using WorkerLib; namespace SyncContextExample { internal class Program { private static void Main(string[] args) { Worker worker = new Worker(); worker.Started += (sender, args) => Console.WriteLine("Запустили работу"); worker.Completed += (sender, args) => Console.WriteLine("Работа завершена"); worker.DoWork(); Console.ReadKey(); } } }