貴重なご意見をありがとうございました。現在の解決策は次のとおりです。DispatcherService
通知する必要があるすべてのクラスの基本クラスに注入されるを実装しましたPropertyChanged
:
public class WPFUIDispatcherService : IDispatcherService
{
public void Invoke(Action action)
{
// check if the calling thread is the ui thread
if (Application.Current.Dispatcher.CheckAccess())
{
// current thread is ui thread -> directly fire the event
action.DynamicInvoke();
}
else
{
// current thread is not ui thread so marshall
// the event to the ui thread
Application.Current.Dispatcher.Invoke(action);
}
}
}
、NotifyPropertyChangedBase
キーラインはdispatcher.Invoke( .. )
:
public class NotifyPropertyChangedBase : INotifyPropertyChanged
{
private IDispatcherService dispatcher;
// inject dispatcher service by unity
[Dependency]
public IDispatcherService Dispatcher { set { dispatcher = value; } }
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged<T>(
Expression<Func<T>> propertyExpression
)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
MemberExpression memberExpression =
propertyExpression.Body as MemberExpression;
if (memberExpression != null)
{
dispatcher.Invoke(() =>
handler(this, new PropertyChangedEventArgs(
memberExpression.Member.Name
)
)
);
}
else
{
throw new ArgumentException(
"RaisePropertyChanged event " +
"was not raised with a property: " +
propertyExpression);
}
}
}
}
ReportService
:_
public class ReportService : NotifyPropertyChangedBase, IReportService
{
private volatile Report report;
public Report { get { return report; } }
CreateReport()
{
lock(this) {
do some work computing result
report = result
RaisePropertyChanged(() => Report)
}
}
私のサービスの呼び出し
IsBusy = true;
Task.Factory.StartNew(() =>
{
reportService.CreateReport();
}).
ContinueWith(task =>
{
IsBusy = false;
},
TaskScheduler.FromCurrentSynchronizationContext());
ReportService
アプリケーションは設計されていますが、バックグラウンドタスクまたはフォアグラウンドで透過的に実行できるようになりました。いずれの場合も、UIスレッド内でイベントが発生することRaisePropertyChanged
を保証します。WPFUIDispatcherService