应用程序调用了为不同线程编组的接口。

huangapple go评论91阅读模式
英文:

'The application called an interface that was marshalled for a different thread

问题

我尝试创建一个线程并在其中操作UI控件,然后收到了一个异常:System.Runtime.InteropServices.COMException: '应用程序调用了一个为不同线程封送的接口。' 通过搜索,我发现这是一个非常常见的问题,下面是我找到的一种方法:

Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
    {
        // 在这里编写你的UI更新代码!
    }
);

但是这会引发另一个异常:System.InvalidOperationException: '在意外的时间调用了一个方法。' 我不知道正确的方法是什么。

private void MessageReceived(string message_content)
{
    InvertedListView.Items.Add(new Message(message_content, DateTime.Now,HorizontalAlignment.Left));
}

static bool flag = true;

Thread thread = new Thread(() =>
{
    FileSystemWatcher watcher = new FileSystemWatcher();
    watcher.Path = "C:\\Users";
    watcher.Filter = "text.txt";
    watcher.NotifyFilter = NotifyFilters.LastWrite;
    watcher.Changed += OnChanged;
    Debug.WriteLine("START!");
    watcher.EnableRaisingEvents = true;

    void OnChanged(object sender, FileSystemEventArgs e)
    {
        if (flag)
        {
            Debug.WriteLine("OnChanged");
            Thread.Sleep(10);
            var lastLine = File.ReadLines(watcher.Path + watcher.Filter, Encoding.UTF8).Last();
            MessageReceived(lastline); // 异常发生在这里
            Debug.WriteLine(lastLine);
            flag = false;
        }
        else
        {
            flag = true;
        }
    }
});

请注意,这只是一种可能的解决方案,具体取决于你的代码和需求。

英文:

I try to create a thread and manipulate UI controls inside it, then I recived an exception
System.Runtime.InteropServices.COMException: 'The application called an interface that was marshalled for a different thread.
Through searching, I found this is a very common problem, here is one way I have found

Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
    {
        // Your UI update code goes here!
    }
);

But this cause another exception
System.InvalidOperationException: 'A method was called at an unexpected time.

I don't know the correct way

private void MessageReceived(string message_content)
{
    InvertedListView.Items.Add(new Message(message_content, DateTime.Now,HorizontalAlignment.Left));
}

static bool flag = true;

Thread thread = new Thread(() =>
{
    FileSystemWatcher watcher = new FileSystemWatcher();
    watcher.Path = "C:\\Users";
    watcher.Filter = "text.txt";
    watcher.NotifyFilter = NotifyFilters.LastWrite;
    watcher.Changed += OnChanged;
    Debug.WriteLine("START!");
    watcher.EnableRaisingEvents = true;

    void OnChanged(object sender, FileSystemEventArgs e)
    {
        if (flag)
        {
            Debug.WriteLine("OnChanged");
            Thread.Sleep(10);
            var lastLine = File.ReadLines(watcher.Path + watcher.Filter, Encoding.UTF8).Last();
            MessageReceived(lastline); // The exception happened here
            Debug.WriteLine(lastLine);
            flag = false;
        }
        else
        {
            flag = true;
        }
    }
});

答案1

得分: 3

要创建/更改UI控件,您需要在UI线程上执行操作。让我给您一个简单的示例:

private DispatcherQueue _dispatcherQueue;

public MainPage()
{
    this.InitializeComponent();
    this.Loaded += MainPage_Loaded;
    _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
}

private async void MainPage_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
    // 这个可以工作,因为这个事件处理程序在UI线程上调用。
    Button button = new();

    // 这个会抛出异常,因为按钮没有在UI线程上创建。
    await Task.Run(() =>
    {
        Button button = new();
    });

    // 这个可以工作,因为使用DispatcherQueue在UI线程上创建按钮。
    this.DispatcherQueue.TryEnqueue(() =>
    {
        Button button = new();
    });

    // 这个可以工作,因为使用DispatcherQueue在UI线程上创建按钮。
    _dispatcherQueue.TryEnqueue(() =>
    {
        Button button = new();
    });
}
英文:

To create/change an UI control, you need to do it on the UI thread. Let me give you a simple example:

private DispatcherQueue _dispatcherQueue;

public MainPage()
{
    this.InitializeComponent();
    this.Loaded += MainPage_Loaded;
    _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
}

private async void MainPage_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
    // This works because this event handler is called on the UI thread.
    Button button = new();

    // This throws an exception because the button is not created on the UI thread.
    await Task.Run(() =>
    {
        Button button = new();
    });

    // This works because the DispatcherQueue is used to create the button on the UI thread.
    this.DispatcherQueue.TryEnqueue(() =>
    {
        Button button = new();
    });

    // This works because the DispatcherQueue is used to create the button on the UI thread.
    _dispatcherQueue.TryEnqueue(() =>
    {
        Button button = new();
    });
}

huangapple
  • 本文由 发表于 2023年8月9日 17:52:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866562.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定