无限循环线程中的C#MVVM模式更新UI?

无限循环线程中的C#MVVM模式更新UI?,c#,wpf,multithreading,mvvm,C#,Wpf,Multithreading,Mvvm,我有一个后台线程来监听数据,所以这个无限循环可以输出数据 并且,我使用一个ObservableCollection绑定一个ListBox并显示日志 我尝试使用Dispather.BeginInvoke,但没有用,它不是实时的。我不知道如何在MVVM中更新UI xaml 代码 private observedcollection\u显示日志; 公共可观察收集显示日志 { 得到 { 返回显示日志; } } 公共Testpro() { _displayLogs=新的ObservableCollec

我有一个后台线程来监听数据,所以这个无限循环可以输出数据

并且,我使用一个
ObservableCollection
绑定一个
ListBox
并显示日志

我尝试使用
Dispather.BeginInvoke
,但没有用,它不是实时的。我不知道如何在MVVM中更新UI

xaml


代码

private observedcollection\u显示日志;
公共可观察收集显示日志
{
得到
{
返回显示日志;
}
}
公共Testpro()
{
_displayLogs=新的ObservableCollection();
运行(新操作(outputData));
}
私有void outputData()
{
字符串str=“”;
while(true)
{
字符串newString=GetInfoString();
if(string.IsNullOrWhiteSpace(newString)| | str==newString)
继续;
str=新闻字符串;
Debug.WriteLine(str);
Application.Current.Dispatcher.BeginInvoke((操作)委托)()
{
DisplayLogs.Add(str);
});
}
}
*编辑:


GetInfoString
将由dll文件调用。

您真的应该使用为这种更新设计的东西。我将推荐微软的反应式框架(NuGet“System.Reactive”和“System.Reactive.Windows.Threading”)

然后您可以在
\u displayLogs=newobservedcollection()之后执行此操作行:

IDisposable subscription = 
    Observable
        .Interval(TimeSpan.FromSeconds(1.0))
        .Select(_ => GetInfoString())
        .Where(newString => !string.IsNullOrWhiteSpace(newString))
        .DistinctUntilChanged()
        .ObserveOnDispatcher()
        .Subscribe(newString =>
        {
            Debug.WriteLine(newString);
            DisplayLogs.Add(newString);
        });
这应该每秒调用
GetInfoString()
,并更新您的UI。它处理所有线程和编组问题


如果保留对
subscription
的引用,则可以在任何阶段通过调用
subscription.Dispose()

停止该引用,因此可以使用async wait。您的OutputData方法可以如下所示:

private async void OutputData(IProgress<string> onProgress)
{
    await Task.Factory.StartNew(() =>
    {
        string str = string.Empty;

        while (true)
        {
            string newString = GetInfoString();
            if(string.IsNullOrWhiteSpace(newString) || str == newString)
                continue;

            str = newString;

            // call the UI to update your bound collection
            onProgress.Report(str);

            // give the ui some time to respond before continue with your endless-loop
            Thread.Sleep(200);
        }
    });
}
private async void OutputData(IProgress onProgress)
{
等待任务。工厂。开始新建(()=>
{
string str=string.Empty;
while(true)
{
字符串newString=GetInfoString();
if(string.IsNullOrWhiteSpace(newString)| | str==newString)
继续;
str=新闻字符串;
//调用UI以更新绑定集合
进展报告(str);
//在继续无休止的循环之前,给ui一些时间来响应
睡眠(200);
}
});
}
您可以通过以下方式调用此方法:

OutputData(new Progress<string>((str) =>
{
    DisplayLogs.Add(str);
}));
OutputData(新进度((str)=>
{
DisplayLogs.Add(str);
}));

就是这样

问题似乎是什么?我使用Dispatcher,但无法实时更新UI。您的循环速度太快,WPF无法正常更新,您可能应该在循环结束时让线程休眠几毫秒。您是否考虑过在单独的线程中使用一个而不是无限循环?这将是更简单的代码。谢谢,我从不使用DispatchTimer,也许我可以试试。@BradleyUffner请不要睡线程。有更好的方法可以做到这一点。它总是不等待任何数据,只显示一次@黃柏森 - 对不起,您的意思是等待所有数据并同时显示所有数据吗?如果是这样,那么问题中的代码不会显示这些内容。你能更详细地解释一下吗?是的,我不知道为什么,但是,
Debug.WriteLine
是实时工作来显示的@黃柏森 - 对不起,我知道英语不是你的第一语言,但我很难理解你。我真的很抱歉。哦,对不起,这是我的错。正如您所说,我等待所有数据并在UI中一次显示所有数据,但是
Debug.WriteLine
show是正常的。我认为他们应该同时更新。
private async void OutputData(IProgress<string> onProgress)
{
    await Task.Factory.StartNew(() =>
    {
        string str = string.Empty;

        while (true)
        {
            string newString = GetInfoString();
            if(string.IsNullOrWhiteSpace(newString) || str == newString)
                continue;

            str = newString;

            // call the UI to update your bound collection
            onProgress.Report(str);

            // give the ui some time to respond before continue with your endless-loop
            Thread.Sleep(200);
        }
    });
}
OutputData(new Progress<string>((str) =>
{
    DisplayLogs.Add(str);
}));