试图通过其他任务修改GUI

本文关键字:任务 修改 GUI 其他 | 更新日期: 2023-09-27 18:12:34

我一直试图在TCP连接之前/之后修改一些GUI元素,我试图同步和非同步执行。

public async void ConnectAsync(String h, String p, String n)
{
    if (connected)
        return;
    try
    {
        hostname = new HostName(h);
        port = p;
        nickname = n;
        await sock.ConnectAsync(hostname, port);
        connected = true;
        if (Connected != null)
            Connected(this, EventArgs.Empty);
    }
    catch (Exception e)
    {
        sock.Dispose();
        hostname = null;
        port = null;
        nickname = null;
        if (ConnectionFailed != null)
            ConnectionFailed(this, EventArgs.Empty);
    }
}

上面的方法由GUI类调用(下面的代码):

private void ConnectButtonClicked(object sender, RoutedEventArgs e)
{
    string nickname;
    if (Bar.Visibility == Windows.UI.Xaml.Visibility.Visible)
        Bar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
    if (Status.Visibility == Windows.UI.Xaml.Visibility.Collapsed)
        Status.Visibility = Windows.UI.Xaml.Visibility.Visible;
    qc.ConnectionFailed += new ConnectionFailedEventHandler(ConnectionFailedEventHandler);
    qc.Connected += new ConnectedEventHandler(ConnectedEventHandler);
    nickname = Nickname.Text;
    /* HERE */
    Task.Run(() => qc.ConnectAsync("irc.quakenet.org", "6667", nickname));
    updateStatus("Connecting...");
    ConnectButton.IsEnabled = false;
    Nickname.IsEnabled = false;
    ProgLanguages.IsEnabled = false;
}

看到这个方法引发了两个不同的事件…

如果我像这样调用这个方法,使用Task.Run(..),这些事件被引发,当它们被处理时,代码试图通过这个线程修改GUI,并抛出异常。

如果我在没有Task.Run(..)的情况下调用该方法,GUI会冻结,并且我不能修改元素以显示它正在"连接"或类似的东西。

知道我该怎么做吗?

试图通过其他任务修改GUI

首先,避免使用async void,因此将ConnectAsync更改为返回Task

然后,您的事件处理程序可以只做await qc.ConnectAsync(...),根本不需要Task.Run

您需要使用Control.Invoke()

我只是在这里回答了同样的问题:后台工作人员报告字符串从一个方法

你需要通过调用control . invoke ()

来包装你对任何UI控件的调用

规则是:任何UI控件都不能被创建它的线程之外的其他线程访问。所以你需要"请求"UI线程执行更新UI控件的代码。这是Invoke方法(继承自Control类)的工作