GTK GUI冻结async / await和Progress <t> </t>

时间:2014-08-02 14:31:22

标签: c# gtk async-await gtk#

我使用GTK#来构建GUI。有些数据在后台处理,我希望看到有关用户界面进度的一些信息。以下是一些代码,展示了我尝试这样做的方式:

using System;
using Gtk;
using System.Threading.Tasks;
using System.Threading;

public partial class MainWindow: Gtk.Window
{
    //a button and a textfield
    private VBox VB = new VBox();
    private Button B = new Button("Push dis");
    private Label L = new Label("0");

    public MainWindow () : base (Gtk.WindowType.Toplevel)
    {

        B.Clicked += OnClickEvent;
        ////////////////////
        VB.PackStart (B);
        VB.PackStart (L);
        Add (VB);
        ShowAll ();
        Build ();
    }

    protected void OnDeleteEvent (object sender, DeleteEventArgs a)
    {
        Application.Quit ();
        a.RetVal = true;
    }

    //async method incrementing variable, simulating some work and sending its progress
    protected async Task CounterGUIUpdateAsync(IProgress<string> progress)
    {
         await Task.Run (() => {
            for (int i = 0; i <= 10000; i++) {
                Thread.Sleep (100);
                if(progress != null)
                {
                    var stri = Convert.ToString(i);
                    progress.Report(stri);

                }
            }
        });
    }

    //event handler for the button
    protected async void OnClickEvent(object sender, EventArgs e)
    {
        var ProgressIndicator = new Progress<string> (ReportProgress);
        await CounterGUIUpdateAsync (ProgressIndicator);
    }

    //action connected to the progress instance 
    protected void ReportProgress(string value)
    {
        L.Text = value;
    }
}

运行代码将按预期启动,但在某些时候,显示的计数器可能会卡住。 GUI不再更新,如果已经最小化则变黑。它仍然有用。

非常感谢帮助。

1 个答案:

答案 0 :(得分:2)

我认为你的问题是你在使用Gtk + API时没有使用主线程(gui线程)。您需要使用Gtk.Application.Invoke()传递操作UI的委托,因此操作在正确的线程中执行。

您可以阅读有关此here的更多信息。