2013-11-01 4 views
1

Я хочу обновить DataGrid из нескольких потоков в WPF (C#). Я использую dataGrid.Dispatcher.BeginInvoke() и dataGrid.Dispatcher.Invoke(), но они замораживают программу (основной поток). Как обновить dataGrid из нескольких потоков с таймаутом (потому что я использую веб-сервис, который может быть недоступен).Обновление DataGrid из нескольких потоков

+0

Я предполагаю, что вы выполняете вызов веб-службы внутри метода, который вызывается диспетчером. Это, конечно же, заморозит пользовательский интерфейс. Вызовите веб-службу из фонового потока (* перед вызовом 'Invoke') и передайте результат в поток пользовательского интерфейса' Invoke'. – Clemens

+0

Привет Клеменс. Можно ли показать мне пример? Я новичок в многопоточности. –

ответ

1

Если вы не нуждаетесь в DataGrid редактирования должно быть сделано в резьбе, вы можете запустить их в основной поток, как это:

this.Invoke((Action)delegate 
{ 
    //Edit the DataGrid however you like in here 
}); 

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

+0

-> ваш ответ не содержит тайм-аута. также он бросает исключение. однако спасибо ... –

+0

@ Babak.Abad Действительно? Что это за исключение? Потому что я использовал это, и он всегда работал. И вы установите таймаут после вызова так, чтобы он запускался в потоке, а не в основном потоке. – AlphaDelta

+0

простите меня AlphaDelta. Вы имели в виду this.Dispatcher.Invoke (...)? –

3

Использовать Task асинхронно отсылать запрос веб-службы. Для этого вам, вероятно, потребуется преобразовать стиль EAP (основанный на событиях асинхронный шаблон) в стиль TAP (асинхронный шаблон на основе задач). Вот как вы это делаете.

private Task<IEnumerable<YourDataItem>> CallWebServiceAsync() 
{ 
    var tcs = new TaskCompletionSource(); 
    var service = new YourServiceClient(); 
    service.SomeOperationCompleted += 
    (sender, args) => 
    { 
     if (args.Error == null) 
     { 
     tcs.SetResult(args.Result); 
     } 
     else 
     { 
     tcs.SetException(args.Error); 
     } 
    }; 
    service.SomeOperationAsync(); 
    return tcs.Task; 
} 

После того, что в месте, то вы можете использовать новые async и await ключевые слова, чтобы сделать звонок и ждать его возвращения, используя семантику продолжение стиля. Это будет выглядеть так.

private async void Page_Loaded(object sender, System.Windows.RoutedEventArgs e) 
{ 
    IEnumerable<YourDataItem> data = await CallWebServiceAsync(); 
    YourDataGrid.DataSource = data; 
} 

Это все! Это не выглядит намного более элегантным. Это будет выполнять операцию асинхронно на фоновом потоке, а затем привязать результаты к DataGrid в потоке пользовательского интерфейса.

Если услуга WCF недоступна, она выдает исключение и будет прикреплена к Task так, чтобы она распространялась до вызова await. В этот момент он будет введен в исполнение и может быть завернут с помощью try-catch, если это необходимо.

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