How can WinForm host a long run IronPython script, and update UI for progress change

I need a WinForm act as the IronPython host, and during the IronPython run-time, the script can update UI to report its progress. I have the following code, and it does update the UI, but the problem is that the Window is not responsive. I appreciate any help.

namespace TryAsyncReport
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //use python
        private async void button1_Click(object sender, EventArgs e)
        {
            IProgress<ProgressReportInfo> progress = new Progress<ProgressReportInfo>(ReportProgress);
            await Task.Run(() =>
            {
                ScriptEngine engine = Python.CreateEngine();
                ScriptScope scope = engine.CreateScope();
                string script = "for i in range(1000000):\r\n";
                script += "   progress.Report(ProgressReportInfo(i / 10000, str(i / 10000)));\r\n";
                scope.SetVariable("progress", progress);
                scope.SetVariable("ProgressReportInfo", typeof(ProgressReportInfo));
                var code = engine.CreateScriptSourceFromString(script);
                code.Execute(scope);

            });

        }

        private void ReportProgress(ProgressReportInfo info)
        {
            progressBar1.Value = info.Percentage; 
            label1.Text = info.Status; 
        }

    }

    public class ProgressReportInfo
    {
        public ProgressReportInfo(int percentage, string status)
        {
            Percentage = percentage;
            Status = status;
        }
        public int Percentage { set; get; }
        public string Status { set; get; }
    }

}

Answers


You have to Invoke to UI thread:

    private void ReportProgress(ProgressReportInfo info)
    {
        // or better BeginInvoke
        Invoke(() =>
        {
            progressBar1.Value = info.Percentage;
            label1.Text = info.Status;
        });
    }

and you don't need to await for Task.Run.

Also, consider do not report every bit of progress change, but let say every 1000 changes.

Other solution is to use polling watcher (your script change value of volatile variable, this value is checked in the timer)


Need Your Help

Can I generate a Flex web and Air desktop app from the same source code?

flex air adobe desktop flexbuilder

I'm new to Air. I've got an existing Flex 2 application which I'm considering bringing into Flexbuilder 3. My question is can I use the same base application (and source code) to make the Air ver...

Cometd : Multiple tabs for online-users management creating false online-status

java spring comet cometd

I am working on a Spring-MVC based web-app which uses Cometd for chat purposes. For real-time management of which user is online, we are sending notifications when the user is online. So when windo...