Я использую SynchronizationContext
как средство синхронизации с потоком графического интерфейса для WinForms и WPF. Недавно я столкнулся с проблемой асинхронных обратных вызовов старого стиля:
private void Button_Click(object sender, RoutedEventArgs e)
{
uiContext = SynchronizationContext.Current;
var cl = new TcpClient();
cl.BeginConnect("127.0.0.1", 22222, ConnectedCallback, null);
}
public void ConnectedCallback(IAsyncResult result)
{
if (SynchronizationContext.Current != uiContext)
uiContext.Post(x => MyUIOperation(), null);
else
MyUIOperation();
}
public void MyUIOperation()
{
Title = "Connected";
}
private SynchronizationContext uiContext;
Это вызовет исключение, потому что SynchronizationContext.Current
в функции обратного вызова равно захваченному, и поэтому операция пользовательского интерфейса выполняется в рабочем потоке обратного вызова.
Использование точно такого же кода в WinForms работает так, как я и ожидал.
На данный момент в качестве обходного пути я вместо этого фиксирую текущий ManagedThreadId
и сравниваю его в обратном вызове. Каков правильный способ справиться с этим?
Обновлять:
Я должен добавить, что я изменяю очень старый существующий класс, который в настоящее время использует следующую конструкцию:
if (control.InvokeRequired())
control.BeginInvoke(SomeFunction);
else
SomeFunction();
Я пытаюсь удалить зависимость WinForms, не оказывая большого влияния на клиентов этого класса. SomeFunction()
вызывает события, поэтому, если я просто вызову uiContext.Send() или uiContext.Post() , порядок выполнения изменится, поскольку Post() всегда ставит вызов в очередь, а Send() всегда блокируется.
Кроме того, это всего лишь очень маленький фрагмент кода, показывающий корень моей проблемы. На самом деле функция, выполняющая Post(), может быть вызвана из основного потока.
Это нацелено на .NET 4.0
if (SynchronizationContext.Current != uiContext)
? Почему бы не всегда вызыватьPost
? - person Yacoub Massad   schedule 28.12.2015MyUIOperation()
нужно было бы вызывать немедленно, если функцияConnectedCallback
вызывается из основного потока. Если я используюPost()
, этого не происходит, вызов всегда откладывается. Это просто очень урезанный пример, иллюстрирующий, что в случаеConnectedCallback
SynchronizationContext.Current
такой же, как и в основном потоке. Таким образом, имитацияControl.InvokeRequired
не работает в WPF, как я это делаю в коде. Но это происходит в WinForms. - person Night94   schedule 28.12.2015SynchronizationContext.Current
внутри обратного вызова является той же ссылкой, что иuiContext
. Пробовал на Win8.1 x64, ориентируясь на .NET 4.0. drive.google.com/file/d/0B91vNcnuPv_GNE10Z3doOEtvSms/ - person Leandro   schedule 28.12.2015