Я использую SynchronizationContext
как средство для синхронизации с потоком GUI для WinForms и WPF. Недавно я столкнулся с проблемой со старым стилем асинхронных обратных вызовов:SynchronizationContext.Current в async обратном вызове
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
в функции обратного вызова равно захваченные один, и, следовательно, операция UI выполняются в рабочем поток обратного вызова.
Использование этого же кода в WinForms работает так, как я ожидал.
На данный момент я обнимаю текущий ManagedThreadId
и сравниваю его в обратном вызове. Каков правильный способ справиться с этим?
Update:
Я хотел бы добавить, что я модифицирование очень старый существующий класса, который в настоящее время использует следующую конструкцию:
if (control.InvokeRequired())
control.BeginInvoke(SomeFunction);
else
SomeFunction();
Я пытаюсь удалить зависимость WinForms, не имея большое влияние на клиентов этого класса. SomeFunction()
вызывает события, поэтому, если я просто вызываю uiContext.Send() или uiContext.Post(), порядок выполнения изменяется, поскольку Post() всегда будет стоять в очереди вызова, а Send() всегда будет блокироваться.
Кроме того, это всего лишь очень маленький фрагмент кода, чтобы показать корень моей проблемы. В действительности функция, выполняющая Post(), может быть вызвана из основного потока.
Это нацеливание .NET 4,0
Я бы сказал, создание службы, которая обеспечивает и дает вам контекст пользовательского интерфейса синхронизации является путь. Затем всегда добавляйте эту службу к любой части кода, в которой вы нуждаетесь, и вызываете сообщение в контексте без каких-либо проверок везде, где вы должны быть уверены, что он выполняется на переднем плане. –
Можете ли вы разместить точное сообщение и трассировку стека за исключением, которое вы получаете? – Leandro
«Вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток." – Night94