2017-10-04 68 views
4

我正在使用RxUI 8的最新版本,但我認爲這會發生在以前的版本中。ReactiveUI命令併發(WebClient)

我在我的WPF應用程序中定義該ReactiveCommand:

GetWebsiteCommand = ReactiveCommand.CreateFromTask(DownloadString); 

private async Task<string> DownloadString() 
{ 
    using (var client = new WebClient()) 
    { 
     return await client.DownloadStringTaskAsync("http://www.google.es"); 
    } 
} 

當執行命令,下面的異常被拋出:

System.InvalidOperationException」在System.Reactive.Core。 DLL:因爲不同的線程 擁有它

的 調用線程不能訪問該對象10

這是怎麼發生的?我沒有創建任何新的線程!

這是堆棧跟蹤:

System.InvalidOperationException」在System.Reactive.Core.dll:因爲不同的線程 擁有它

at System.Windows.Threading.Dispatcher.VerifyAccess() 
    at System.Windows.DependencyObject.GetValue(DependencyProperty dp) 
    at System.Windows.Controls.Primitives.ButtonBase.get_Command() 
    at System.Windows.Controls.Primitives.ButtonBase.UpdateCanExecute() 
    at System.Windows.Controls.Primitives.ButtonBase.OnCanExecuteChanged(Object sender, EventArgs e) 
    at System.Windows.Input.CanExecuteChangedEventManager.HandlerSink.OnCanExecuteChanged(Object sender, EventArgs e) 
    at ReactiveUI.ReactiveCommand.OnCanExecuteChanged() 
    at ReactiveUI.ReactiveCommand`2.<.ctor>b__9_5(Boolean _) 
    at System.Reactive.AnonymousSafeObserver`1.OnNext(T value) 
    at System.Reactive.Linq.ObservableImpl.RefCount`1._.OnNext(TSource value) 
    at System.Reactive.Subjects.FastImmediateObserver`1.EnsureActive(Int32 count) 
    at System.Reactive.Subjects.FastImmediateObserver`1.EnsureActive() 
    at System.Reactive.Subjects.ReplaySubject`1.ReplayBase.OnNext(T value) 
    at System.Reactive.Subjects.ReplaySubject`1.OnNext(T value) 
    at System.Reactive.Linq.ObservableImpl.AsObservable`1._.OnNext(TSource value) 
    at System.Reactive.Linq.ObservableImpl.DistinctUntilChanged`2._.OnNext(TSource value) 
    at System.Reactive.Linq.ObservableImpl.CombineLatest`3._.S.OnNext(TSecond value) 
    at System.Reactive.Linq.ObservableImpl.RefCount`1._.OnNext(TSource value) 
    at System.Reactive.Subjects.FastImmediateObserver`1.EnsureActive(Int32 count) 
    at System.Reactive.Subjects.FastImmediateObserver`1.EnsureActive() 
    at System.Reactive.Subjects.ReplaySubject`1.ReplayBase.OnNext(T value) 
    at System.Reactive.Subjects.ReplaySubject`1.OnNext(T value) 
    at System.Reactive.Linq.ObservableImpl.AsObservable`1._.OnNext(TSource value) 
    at System.Reactive.Linq.ObservableImpl.DistinctUntilChanged`2._.OnNext(TSource value) 
    at System.Reactive.Linq.ObservableImpl.Concat`1._.OnNext(TSource value) 
    at System.Reactive.Linq.ObservableImpl.Select`2._.OnNext(TSource value) 
    at System.Reactive.SafeObserver`1.OnNext(TSource value) 
    at System.Reactive.ScheduledObserver`1.Dispatch(ICancelable cancel) 
    at System.Reactive.Concurrency.Scheduler.<>c.<ScheduleLongRunning>b__72_0(Action`1 a, ICancelable c) 
    at System.Reactive.Concurrency.DefaultScheduler.LongRunning.<>c__DisplayClass1_0`1.<ScheduleLongRunning>b__0(Object arg) 
    at System.Reactive.Concurrency.ConcurrencyAbstractionLayerImpl.<>c__DisplayClass7_0.<StartThread>b__0() 
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ThreadHelper.ThreadStart() 
的 調用線程不能訪問該對象
+0

你沒有創建任何新的線程?也許你對Task的概念不熟悉。閱讀[本文](https://docs.microsoft.com/en-us/dotnet/csharp/async)以獲取信息 –

+0

@CamiloTerevinto。不,我沒有創建任何新的線程。我在哪裏創建線程?據我所知,任務不涉及創建任何線程。你知道WebClient.DownloadStringTaskAsync方法是否正在另一個線程上運行任務嗎? – SuperJMN

+0

@CamiloTerevinto你能告訴我,Task.FromResult((=)=> 1)是否在一個新的線程上運行?請停止downvoting,請,並開始給出有用的答案。否則,讓別人去做。 – SuperJMN

回答

2

通過堆棧跟蹤判斷,您正在向命令傳遞一個canExecute管道。對於您提供的任何管道,您有責任確保它在正確的線程上打勾。如果它在後臺線程上打勾,命令CanExecute事件將在同一線程上打勾,因此UI將嘗試更新相關Button上的IsEnabled屬性與錯誤的線程。

所以你可能需要添加一個ObserveOn調用你的canExecute管道。

更新:回答here

+0

謝謝,肯特!但是我沒有傳遞任何CanExecute管道。該命令是用'ReactiveCommand.CreateFromTask(DownloadString)'行創建的;'所以我只通過任務。你可以,請運行代碼?用這些簡單的線條就可以重現問題。 – SuperJMN