Вопрос больше по проектированию, но применительно к C#.
Есть класс логики, который реализует логику приложения. Есть класс формы, который владеет первым классом. Класс логики содержит пул потоков, в которых генерируются события. Он эти события обрабатывает и пересылает форме. В результате в форме вызываются обработчики событий из сторонних потоков, и приходится вызывать .InvokeRequired, .Invoke и т.п.
Мне кажется, в правильной структуре, не должно быть такой ситуации, что форма должна заботиться о том, чтобы вызов был из нужного потока. Если это верно, то тогда вопрос по реализации: как правильно сделать, чтобы класс логики всегда вызывал события из того потока, в котором был создан?
Передавать родительский контрол ему в конструктор, у которого потом зызывать .Invoke — решение очевидное, но классу логики ни к чему связь с System.Windows.Forms.Control.
Re: Вызвать события класса в потоке, в котором он был создан
Здравствуйте, Павел А.Ануфриков, Вы писали:
ПАА>Передавать родительский контрол ему в конструктор, у которого потом зызывать .Invoke — решение очевидное, но классу логики ни к чему связь с System.Windows.Forms.Control.
Вместо Control логика может знать про более абстрактную и более нужную в данном случае вещь — SynchronizationContext. Используйте его.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Вызвать события класса в потоке, в котором он был соз
_FR>Вместо Control логика может знать про более абстрактную и более нужную в данном случае вещь — SynchronizationContext. Используйте его.
А я правильно понял, что нельзя вызвать произвольный делегат, а можно только SendOrPostCallback ? Т.е., если мне нужно вызвать собственный делегат формы, нужно сначала вызвать SendOrPostCallback, а из него уже вызывать делегат формы?
Re[3]: Вызвать события класса в потоке, в котором он был соз
Здравствуйте, Павел А.Ануфриков, Вы писали:
ПАА>А я правильно понял, что нельзя вызвать произвольный делегат, а можно только SendOrPostCallback ? Т.е., если мне нужно вызвать собственный делегат формы, нужно сначала вызвать SendOrPostCallback, а из него уже вызывать делегат формы?
Неясно, что такое собственный делегат формы, но можно делать так:
syncContext.Post(
_ => form.Foo(...),
null);
Re[3]: Вызвать события класса в потоке, в котором он был соз
Здравствуйте, Павел А.Ануфриков, Вы писали:
_FR>>Вместо Control логика может знать про более абстрактную и более нужную в данном случае вещь — SynchronizationContext. Используйте его.
ПАА>А я правильно понял, что нельзя вызвать произвольный делегат, а можно только SendOrPostCallback ? Т.е., если мне нужно вызвать собственный делегат формы, нужно сначала вызвать SendOrPostCallback, а из него уже вызывать делегат формы?
Да. Обычно это никогда не представляет трудностей.
Help will always be given at Hogwarts to those who ask for it.
Re: Вызвать события класса в потоке, в котором он был создан
объект AsyncOperation захватил текущий контекст, который будет использоваться в последствии для выполнения в нем нужных методов.
А потом в методах класса логики, в которых нужно, чтобы операция происходила в том же потоке, вызываете:
_asyncOperation.Post(sendOrPostCallback, null);
Поток, в котором выполнится операция зависит от контекста, в котором был создан объект AsyncOperation в конструкторе. Если SynchronizationContect.Current был null (т.е. объект был создан не в GUI-потоке), то будет создан новый контекст и делегаты будут выполнятся в каком-то потоке из thread pool'а. Если же объект был создан в GUI-потоке (в котором SynchronizationContext.Current выставлен в WindowsFormsSynchronizationContext, то этот контекст и соответственно GUI-поток и будeт использоваться для выполнения делегатов.
В принципе можно не использовать классы AsyncOperationManager и AsyncOperation, а использовать напрямую SynchronizationContext, но эти классы предоставляют более высокоуровневую оболочку над SynchronizationCotnext. В частности, SynchronizationContext.Current может быть null, и это нужно проверять и в этом случае создавать новый SynchronizationContext, а классы AsyncOperationManager и AsyncOperation делают это за вас.