Progress report : Need help understanding how it works

旧街凉风 提交于 2020-06-01 06:54:13

问题


I'm discovering this and can't get to understand how it works. I have a progress bar in my main form and a menuStrip with a few maintenance functions on a mysql DB. I'd like to monitor progress for each of them. So I have a class report and a Progress progress. My declarations are as follow :

 ProgressReportModel report = new ProgressReportModel();
 Progress<ProgressReportModel> progress = new Progress<ProgressReportModel>();
 progress.ProgressChanged += ReportProgress;

Now for each of the functions, I usually start with :

        report.max = count;
        report.visibility = true;
        report.PercentageComplete = 0;
        showtheProgress(progress);

with ShowtheProgress because I didn't find a way to convert from Progress to IProgress:

   private void showtheProgress(IProgress<ProgressReportModel> progress)
    {
        progress.Report(report);
    }

My issue is that this works for some functions but not all. One difference that i can see if that it works with functions which are async but not with functions which are not async. To void flooding with code, just gonna put one function which is not working (ie the progressbar is not even showing up):

    private void getMp3Files()
    {
        Globals.counttot = Directory.GetFiles(Globals.pathdir, "*.mp3", SearchOption.AllDirectories).Length;
        report.max = Globals.counttot;
        report.visibility = true;
        report.PercentageComplete = x; 
        showtheProgress(progress);
        DirectoryCopy(Globals.pathdir);
        report.visibility = false;
        report.PercentageComplete = 0;
        showtheProgress(progress);
    }
    private void DirectoryCopy(string sourceDirName)
    {
        DirectoryInfo dir = new DirectoryInfo(sourceDirName);
        DirectoryInfo[] dirs = dir.GetDirectories();
        FileInfo[] files = dir.GetFiles("*.mp3");
        foreach (FileInfo file in files)
        {
            string temppath = Path.Combine(sourceDirName, file.Name);
            Mp3 tmp_mp3 = Globals.getTags(temppath);
            Globals.AddRowDs(tmp_mp3, false);
            report.PercentageComplete = x; //not part of this code but it's a counter
            showtheProgress(progress);
        }
        foreach (DirectoryInfo subdir in dirs) DirectoryCopy(subdir.FullName);
    }

Thanks in advance!


回答1:


It's not completely clear from the code that you have posted but my guess is that you have this problem because of the way how winforms works with threads and one of the reasons why the async was 'invented'.

A windows form is based on something like a message queue. Everything that you do on that form like moving your mouse, clicking a button, moving/resizing the form, typing and many more is converted to events and placed in this queue. In the background there is something constantly checking this queue for new events and executing them, one of these events is to draw the screen (paint), basically showing your form on the screen. You can only see the changes that are made (like showing a progress bar) during these paint events. If the time between these paint events is too long you see the message "Not responding".

Some of these events are also clicks on a button and these will execute all the code that you made. If the process of this event takes too long, then you will hold up the message queue and create the "Not responding" message. In order to avoid this, it's suggested to make these events as quick as possible, if you want to execute something that takes a long time, make it on another thread (see BackgroundWorker for an example). One downside of this is that it's not easy to communicate with the form (typically checking InvokeRequired and calling Invoke)

Here is where the async/await comes to help you. If you have a button click, and your code encounters an await that is not done yet, then it will add some code that, once the awaited method is done, it will add an event to the message queue to continue from this point in your code and end the event. This means that the rest of the events in the message queue (like showing that progress bar, displaying some text or handling other button clicks) are possible.

Just to be complete, some can suggest that you can sprinkle your code with Application.DoEvents(), these will force the message queue to be processed while you are still inside the method. This is a quick and dirty way that some people take without knowing the full implications of this. Know that it exists but avoid it.



来源:https://stackoverflow.com/questions/61984119/progress-report-need-help-understanding-how-it-works

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!