首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在WPF中安全访问UI (Main)线程

在WPF中安全访问UI (Main)线程
EN

Stack Overflow用户
提问于 2012-07-24 14:20:49
回答 2查看 140.4K关注 0票数 109

我有一个应用程序,每当我正在观察的日志文件以以下方式更新(附加了新文本)时,它就会更新我的datagrid:

代码语言:javascript
复制
private void DGAddRow(string name, FunctionType ft)
    {
                ASCIIEncoding ascii = new ASCIIEncoding();

    CommDGDataSource ds = new CommDGDataSource();

    int position = 0;
    string[] data_split = ft.Data.Split(' ');
    foreach (AttributeType at in ft.Types)
    {
        if (at.IsAddress)
        {

            ds.Source = HexString2Ascii(data_split[position]);
            ds.Destination = HexString2Ascii(data_split[position+1]);
            break;
        }
        else
        {
            position += at.Size;
        }
    }
    ds.Protocol = name;
    ds.Number = rowCount;
    ds.Data = ft.Data;
    ds.Time = ft.Time;

    dataGridRows.Add(ds); 

    rowCount++;
    }
    ...
    private void FileSystemWatcher()
    {
        FileSystemWatcher watcher = new FileSystemWatcher(Environment.CurrentDirectory);
        watcher.Filter = syslogPath;
        watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
            | NotifyFilters.FileName | NotifyFilters.DirectoryName;
        watcher.Changed += new FileSystemEventHandler(watcher_Changed);
        watcher.EnableRaisingEvents = true;
    }

    private void watcher_Changed(object sender, FileSystemEventArgs e)
    {
        if (File.Exists(syslogPath))
        {
            string line = GetLine(syslogPath,currentLine);
            foreach (CommRuleParser crp in crpList)
            {
                FunctionType ft = new FunctionType();
                if (crp.ParseLine(line, out ft))
                {
                    DGAddRow(crp.Protocol, ft);
                }
            }
            currentLine++;
        }
        else
            MessageBox.Show(UIConstant.COMM_SYSLOG_NON_EXIST_WARNING);
    }

当为FileWatcher引发事件时,因为它创建了一个单独的线程,所以当我尝试运行dataGridRows.Add(Ds)时;为了添加新行,程序在调试模式期间崩溃,没有给出任何警告。

在Winforms中,使用Invoke函数可以很容易地解决这个问题,但我不确定在WPF中该如何处理。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-24 14:25:00

您可以使用

Dispatcher.Invoke(Delegate, object[])

Application的(或任何UIElement的)调度器上。

例如,您可以像这样使用它:

代码语言:javascript
复制
Application.Current.Dispatcher.Invoke(new Action(() => { /* Your code here */ }));

代码语言:javascript
复制
someControl.Dispatcher.Invoke(new Action(() => { /* Your code here */ }));
票数 231
EN

Stack Overflow用户

发布于 2012-07-24 14:31:33

最好的方法是从UI线程获取一个SynchronizationContext并使用它。这个类抽象了对其他线程的编组调用,使测试变得更容易(与直接使用WPF的Dispatcher形成对比)。例如:

代码语言:javascript
复制
class MyViewModel
{
    private readonly SynchronizationContext _syncContext;

    public MyViewModel()
    {
        // we assume this ctor is called from the UI thread!
        _syncContext = SynchronizationContext.Current;
    }

    // ...

    private void watcher_Changed(object sender, FileSystemEventArgs e)
    {
         _syncContext.Post(o => DGAddRow(crp.Protocol, ft), null);
    }
}
票数 56
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11625208

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档