Асинхронная функция - обратный вызов с использованием объекта, принадлежащего основному потоку - PullRequest
1 голос
/ 15 декабря 2009

В моем приложении .NET, созданном с WPF и C #, я вызываю асинхронную функцию, используя AsyncMethodCaller . В обратном вызове я хотел бы обновить некоторые данные в графическом интерфейсе, но я не позволил, поскольку это принадлежит основному потоку. Как мне это сделать?

  • вызвать обновление в главном потоке? Как?
  • Передайте объект (например, ViewModel) в качестве состояния обратному вызову и обновите данные об этом - который снова связан с GUI?
  • Как-то иначе?

Какой самый распространенный, рекомендуемый способ справиться с этим?

Ошибка времени выполнения:

Вызывающий поток не может получить доступ к этому объекту, поскольку он принадлежит другому потоку.

Ответы [ 3 ]

3 голосов
/ 15 декабря 2009

Вам необходимо вызвать метод с помощью Dispatcher, вызвав метод Dispatcher.Invoke. В этой статье MSDN подробно объясняется, как обновить пользовательский интерфейс в WPF из асинхронных операций.

2 голосов
/ 15 декабря 2009

Bambuska,

Использование Dispatcher действительно намного проще, чем вы думаете. Пожалуйста, посмотрите на мой код:

public class MyViewModel : BaseViewModel    
{    
    public int Result    
    {    
        get { return _result; }    
        set    
        {    
            _result = value;     

            Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new WorkMethod(delegate
                {
                    this._result = SampleMethodChangingResult();
                }));

            this.RaisePropertyChanged("Result");    
        }    
    }    
}  

Это должно работать (в моем случае это так). В любом случае, пожалуйста, держите меня в курсе.

0 голосов
/ 15 декабря 2009

Я попытался передать объект ViewModel как asyncState, чтобы обратный вызов мог получить доступ к этому объекту. Обратный вызов обычно обновляет некоторое свойство значением, полученным от вызова асинхронной функции. В любом случае ViewModel будет там, где я хочу обновить статус. Это правильный способ справиться с этим? Или я всегда должен использовать Dispatcher.Invoke?

ViewModel:

public class MyViewModel : BaseViewModel
{
    public int Result
    {
        get { return _result; }
        set
        {
            _result = value; 
            this.RaisePropertyChanged("Result");
        }
    }
}

Вызов функции:

caller.BeginInvoke(num1, num2, new AsyncCallback(CallbackMethod), _myViewModel);

Обратный вызов обновляет модель представления:

private void CallbackMethod(IAsyncResult ar)
{
    var result = (AsyncResult)ar;
    var caller = (AsyncMethodCaller)result.AsyncDelegate;
    var vm = ar.AsyncState as MyViewModel;
    int returnValue = caller.EndInvoke(ar);
    vm.Result = returnValue; 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...