英文:
'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();
});
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论