C# 在长时间运行的流程中,使用ReactiveUI、Observables、SubscribeOn和ObserveOn在UI中显示输出日志
我有一个WPF应用程序,它将启动一个长时间运行的任务(60秒以上),该任务使用C# 在长时间运行的流程中,使用ReactiveUI、Observables、SubscribeOn和ObserveOn在UI中显示输出日志,c#,.net,wpf,multithreading,system.reactive,C#,.net,Wpf,Multithreading,System.reactive,我有一个WPF应用程序,它将启动一个长时间运行的任务(60秒以上),该任务使用System.Reactive.Subject定期推送状态消息。当时的想法是,我可以从我的ViewModel订阅observable,并让ReactiveUI通过数据绑定自动更新我的UI。除了文本框没有实时更新之外,这一切都可以正常工作。它仅在长时间运行的任务完成后更新。我想这是因为我的UI线程被阻止,无法更新 在这种假设下,我的研究表明,我可以使用SubscribeOn将订阅放在后台线程上,然后使用ObserveOn
System.Reactive.Subject
定期推送状态消息。当时的想法是,我可以从我的ViewModel订阅observable,并让ReactiveUI通过数据绑定自动更新我的UI。除了文本框没有实时更新之外,这一切都可以正常工作。它仅在长时间运行的任务完成后更新。我想这是因为我的UI线程被阻止,无法更新
在这种假设下,我的研究表明,我可以使用SubscribeOn
将订阅放在后台线程上,然后使用ObserveOnDispatcher
将通知推回到UI线程。然而,这仍然没有产生我想要的结果——UI只是在长时间运行的任务返回后才更新
有人能告诉我需要做些什么来实时更新输出日志吗?下面是相关的代码片段
XAML:
视图模型:
private string _output;
public string Output // Data bound in XAML
{
get { return _output; }
set { this.RaiseAndSetIfChanged(ref _output, value); }
}
public void StartConversion()
{
_edmxConverter.Convert(); // Long-running Task
}
public ConversionOutputWindowViewModel(Utilities.Converters.EdmxConverter converter)
{
_edmxConverter = converter;
_compositeDisposable.Add(_edmxConverter.Output
.SubscribeOn(NewThreadScheduler.Default)
.ObserveOnDispatcher()
.Subscribe(s => Output = Output += s));
//_compositeDisposable.Add(_edmxConverter.Output.Subscribe(s => Output = Output += s));
}
长时间运行的任务功能:
public Subject<string> Output { get; }
Output = new Subject<string>(); //In ctor
private void PrintReplacement(XAttribute attribute, string oldValue, string newValue, int level, Verbosity minVerbosity = Verbosity.Informational)
{
if (Verbosity < minVerbosity) return;
Output.OnNext($"{new string('\t', level)}{attribute.Name}: {oldValue} -> {newValue}{Environment.NewLine}");
}
公共主题输出{get;}
输出=新主题()//内导体
私有void PrintReplacement(XAttribute属性,字符串oldValue,字符串newValue,int级别,Verbosity minVerbosity=Verbosity.information)
{
if(Verbosity{newValue}{Environment.NewLine}”);
}
将我的长时间运行的任务函数调用封装在
等待任务中会有帮助吗?我在抓救命稻草。我对.NET线程没有很好的工作知识。您使用的是主题,所以.SubscribeOn(NewThreadScheduler.Default)
什么都不做。(标准的旧式击鼓)不要使用主题
长时间运行的进程应该是返回IObservable
(而不是具有公开属性的类)的方法调用。T
应该是您想要接收的状态更新。当任务完成时,你就完成了。如果任务失败,您将返回错误
理想情况下,使用Observable.Create返回IObservable的方法可以定义需要完成的工作
public IObservable<string> Convert()
{
return Observable.Create<string>(observer=>
{
//do stuff here.
//Call observer.OnNext with status messages
//When done call observer.OnCompleted()
});
}
public IObservable Convert()
{
返回可观察的。创建(观察者=>
{
//在这里做事。
//使用状态消息调用observer.OnNext
//完成后,调用observer.OnCompleted()
});
}
由于您没有说明长期运行的任务是什么,我无法再帮助您实施。感谢您的回复。这是非常有趣的,可能真的有助于展示我对反应式的最基本的理解。你介意进一步说明为什么使用主题是不好的吗?我的理解是,“Subject”只是一个对象,它提供了“IObservable”和“IObserver”的标准实现。我想使用一个主题,因为我有几个“Print-”方法,它们都在调用“Output.OnNext”。我没有意识到这很重要,否则我会把它包括在问题中。我不确定使用“Observable.Create”时,该模式将如何工作
public Subject<string> Output { get; }
Output = new Subject<string>(); //In ctor
private void PrintReplacement(XAttribute attribute, string oldValue, string newValue, int level, Verbosity minVerbosity = Verbosity.Informational)
{
if (Verbosity < minVerbosity) return;
Output.OnNext($"{new string('\t', level)}{attribute.Name}: {oldValue} -> {newValue}{Environment.NewLine}");
}
public IObservable<string> Convert()
{
return Observable.Create<string>(observer=>
{
//do stuff here.
//Call observer.OnNext with status messages
//When done call observer.OnCompleted()
});
}