我在mvvmcross viewmodel中有一个长时间运行的进程,并希望将其设置为异步(http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx)。
Xamarin的测试版渠道目前支持async关键字。
以下是我目前正在实施异步的示例。 IsBusy标志可以绑定到UI元素并显示加载消息。
这是正确的方法吗?
public class MyModel: MvxViewModel
{
private readonly IMyService _myService;
private bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set { _isBusy = value; RaisePropertyChanged(() => IsBusy); ; }
}
public ICommand MyCommand
{
get
{
return new MvxCommand(DoMyCommand);
}
}
public MyModel(IMyService myService)
{
_myService = myService;
}
public async void DoMyCommand()
{
IsBusy = true;
await Task.Factory.StartNew(() =>
{
_myService.LongRunningProcess();
});
IsBusy = false;
}
}
答案 0 :(得分:30)
你应该避免async void
。当您处理ICommand
时,您需要使用async void
,但应尽量减少其范围。
此修改后的代码将您的操作公开为async Task
,可以进行单元测试并可从代码的其他部分使用:
public class MyModel: MvxViewModel
{
private readonly IMyService _myService;
private bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set { _isBusy = value; RaisePropertyChanged(() => IsBusy); ; }
}
public ICommand MyCommand
{
get
{
return new MvxCommand(async () => await DoMyCommand());
}
}
public MyModel(IMyService myService)
{
_myService = myService;
}
public async Task DoMyCommand()
{
IsBusy = true;
await Task.Run(() =>
{
_myService.LongRunningProcess();
});
IsBusy = false;
}
}
您对IsBusy
的使用很好;这是异步UI中的一种常见方法。
我确实将Task.Factory.StartNew
更改为Task.Run
; Task.Run
的{{1}}代码首选async
。
答案 1 :(得分:6)
MvvmCross现在有MvxAsyncCommand
(参见GitHub commit)。
所以不要这样做
public ICommand MyCommand
{
get
{
return new MvxCommand(async () => await DoMyCommand());
}
}
你可以这样做
public ICommand MyCommand
{
get
{
return new MvxAsyncCommand(DoMyCommand);
}
}
答案 2 :(得分:3)
看起来没问题,除非我最后在await附近添加一个try catch。
public async void DoMyCommand()
{
IsBusy = true;
try{
await Task.Factory.StartNew(() =>
{
_myService.LongRunningProcess();
});
}catch{
//Log Exception
}finally{
IsBusy = false;
}
}
我在博客上使用带有异步的MvxCommand进行了更多示例。与您的示例http://deapsquatter.blogspot.com/2013/03/updating-my-mobile-apps-for-async.html
非常相似答案 3 :(得分:1)
您还可以使用 MethodBinding plugin来避免样板代码(命令),并将您的UI直接绑定到异步方法。
此外,如果您使用Fody PropertyChanged,您的代码将如下所示:
[ImplementPropertyChanged]
public class MyModel: MvxViewModel
{
private readonly IMyService _myService;
public bool IsBusy { get; set; }
public MyModel(IMyService myService)
{
_myService = myService;
}
public async Task DoSomething()
{
IsBusy = true;
await Task.Factory.StartNew(() =>
{
_myService.LongRunningProcess();
});
IsBusy = false;
}
}
您可以进行如下绑定:“点击DoSomething”。
另一方面,为什么不使await Task.Factory.StartNew()
异步,而不是使用_myService.LongRunningProcess
?
看起来会好得多:
public async Task DoSomething()
{
IsBusy = true;
await _myService.LongRunningProcess();
IsBusy = false;
}