2010-05-05 4 views
2

Я пытаюсь отключить части пользовательского интерфейса в приложении .NET на основе опроса, выполненного в фоновом потоке. Фоновый поток проверяет, все ли открыто и работоспособно глобальное подключение к базе данных, которое использует приложение.Многопотоковые делегаты/события

Что мне нужно делать, и предпочтет сделать это без опроса в потоке пользовательского интерфейса, это добавить обработчик событий, который может быть поднят фоновым потоком, если состояние соединения изменится. Таким образом, любая форма может иметь обработчик, который отключит те части пользовательского интерфейса, которые требуют подключения к функции.

Попытка использования объявления прямого события в классе, который содержит подтекст потока, и воссоздание события в фоновом потоке, вызывающее ошибки выполнения кросс-потоков в отношении доступа к элементам управления пользовательского интерфейса из других потоков.

Очевидно, что есть правильный способ сделать это, но у нас ограниченный опыт работы с событиями (в основном, приложения с одним потоком), и почти нет делегатов. Я прочитал документацию и примеры для делегатов, и это похоже на то, что нам нужно, но я не уверен, как заставить его работать в этом случае.

Приложение написано в основном на VB.NET, но пример или помощь на C# тоже хороши.

+0

В dotNET у вас не должно быть постоянно открытого глобального соединения. Прочитайте ConnectionPooling. http://stackoverflow.com/questions/2715714/ –

+0

@ Хенк Холтерман: Вы не можете сделать это заявление, если не знаете его обстоятельств. Кроме того, не рекомендуется с поставщиками, которые Microsoft включает в себя. – AMissico

+0

@ AMissico: Используя мою технику ниже, это не имеет значения (она работает одинаково хорошо ...) –

ответ

2

Вы можете маршал подъема события обратно на поток пользовательского интерфейса. Поскольку это, вероятно, (если вы хорошо спроектировали), выполняемый из отдельного класса, моя рекомендация состояла бы в передаче копии текущего SynchronizationContext в ваш класс, который обрабатывает фоновый процесс.

Вот некоторые примеры код в C#:

public class BackgroundWork 
{ 
    public SynchronizationContext Context { get; private set; } 
    public BackgroundWork(SynchronizationContext context) 
    { 
     this.Context = context; 
    } 

    // Thread handler, etc... 

    // Method to raise event 
    void RaiseEvent() 
    { 
     Context.Post((state) => 
     { 
      // Raise the event 
      this.ConnectionStatusChanged(this, EventArgs.Empty); 
     }, null); 
    } 
} 

Затем, когда вы строите класс (в вашем UI потоке), передать его текущий контекст:

BackgroundWork worker = new BackgroundWork(SynchronizationContext.Current); // This passes the UI thread context... 
worker.Start(); 

(Это, путь, это тот же метод, который использует класс BackgroundWorker, поэтому он работает одинаково как для Windows Forms, так и для WPF ...)

0

Вы решаете перекрестную ошибку выполнения нити с помощью Control.Dispatcher.Invoke:

public void EnventHandlerMethod(object sender, EventArgs e) 
{ 
    myLabel.Dispatch.Invoke(new Action(() => { myLabel.Content = "Updated"; })); 
} 

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

Также это (я думаю) предполагает .NET 3.5

+0

Это разрешает его на стороне подписки клиента, но не на стороне объединения пулов ... –

0

Попробуйте Invoke метод контроля, который Вы хотите изменить, или какого-либо контроля действительно, и поставить небольшую функцию, чтобы сделать работу, которую вы хотите. Или смотрите BeginInvoke для выполнения асинхронной работы.

Просто будьте осторожны резьбами вопросов, изменяя переменные «основная» нить изменения и т.д.

+0

Это (почти) решает его стороне клиентской подписки, но не на стороне объединения пулов ... –

Смежные вопросы