0

I want to use IProgress to report the running status of background task. it can work at Console application, but failed w/ Winform application. I used .net framework 4.6.1, compiled to x64

The Test main is

public class MyTestInvoke
{
    public MyTestInvoke() {}

        public void Run()
        {
            var progress = new Progress<int>(handler_ProgressChanged);

            Type theTest = typeof(MyTest);
            ConstructorInfo theConstructor = theTest .GetConstructor(Type.EmptyTypes);
            object theClassObject = theConstructor.Invoke(new object[] { });

            MethodInfo theMethod = theTest.GetMethod("RunProcess");

            try
            {
                theMethod.Invoke(theClassObject, new object[] { progress });
            }
            catch (Exception ex)
            {
                
            }
        }

        private void handler_ProgressChanged(int returnVal)
        {
            Console.WriteLine("MyTestInvoke::handler_ProgressChanged,thread Id is: {0}, returnVal={1}", Thread.CurrentThread.ManagedThreadId, returnVal);
        }
}

The following code is MyTest

public class MyTest
{
    int sleep = 1;

    public MyTest()
    {

    }

    public void RunProcess(IProgress<int> progress)
    {
        for (int i = 0; i < 4; i++)
        {
            progress.Report(i);
            System.Threading.Thread.Sleep(300);
        }
    }
}

when run at WinForm, just call MyTestInvoke by button event

private void btnTest_Click(object sender, EventArgs e)
{
    this.btnTest.Enabled = false;

    MyTestInvoke mi = new MyTestInvoke();
    mi.Run();
}

Also at Console app, just call the same class the same way,

[STAThread]
static void Main(string[] args)
{
    MyTestInvoke mt = new MyTestInvoke();
    mt.Run();
    Console.ReadLine();
}

When run as console app, the progress handler will be called every loop, but run as Winform, the progress handler will only be activated after RunProcess finished. Even I added an "async Task" to the RunProcess function, both run w/ the same results.

What the difference for both?

Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
Ben
  • 9
  • 4
  • It will work better when you'll remove Thread.Sleep() from the loop. As of now, you'll most probably see all of it printed at once, after the loop is done. What are you testing here, exactly? – Jimi Jul 09 '20 at 04:44
  • After removed the sleep, nothing changed – Ben Jul 09 '20 at 05:21
  • I doubt it. Change the method in `public async Task RunProcess(IProgress progress) { for (int i = 0; i < 4; i++) { progress.Report(i); await Task.Delay(300); Console.WriteLine($"Loop +{i+1}"); } }`. You're not blocking the UI Thread now. See what prints and when. – Jimi Jul 09 '20 at 05:32
  • after changed the sleep to Task.delay, it can work now w/ Winform? but Thread.Sleep cann't. That is a trick or something? – Ben Jul 09 '20 at 06:11
  • the await blabla will stop the thread and return to caller thread, but Thread.Sleep() will only sleep. – Ben Jul 09 '20 at 06:17
  • 2
    There's no trick, there's a [Message Loop](https://learn.microsoft.com/en-us/windows/win32/winmsg/about-messages-and-message-queues), [Window Messages](https://learn.microsoft.com/en-us/windows/win32/learnwin32/window-messages) and you were blocking it. A WinForms app is not a Console app. – Jimi Jul 09 '20 at 06:17

0 Answers0