且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用C#中的任务更新进度条?

更新时间:2023-01-13 08:49:06

ProgressBar控件 [ ^ ]内置支持显示不确定的进度 - 只需设置样式属性 [ ^ ]到 ProgressBarStyle.Marquee

 oi1ProgressStatus.Style = ProgressBarStyle.Marquee; 

await Task.Run(()= >
{
BaseParameters.ErrorBag.Clear();
if (ESignatureService.SignDocuments(documentIds,GlobalVariables.oLoginRO.PersonalSchluessel))
SaveAndPopulateDocuments();

breakFlag = false ;
});

oi1ProgressStatus.Style = ProgressBarStyle.Blocks;



注意:您无法从后台更新UI元素线程,因此您需要使用调用将更新推送回UI线程。如果在UI线程上使用 Task.WaitAny ,则会阻止 Invoke 方法,并导致死锁。使用 async / 等待,这将在后台任务运行时保持UI线程响应。



如果您不能使用 async / 等待,那么请使用 BackgroundWorker [ ^ ]执行任务。


这是基本想法,您可能需要根据自己的需要进行调整。不要尝试自己的军事线索,这只需要遗留代码。 async await 关键字提供了足够的抽象,你不必这样做。

  //  这是按钮点击事件处理程序 
// 注意异步修饰符
private async void ReadWebPageEventHandlerAsync( object sender,RoutedEventArgs e)
{
string text;
// ***插入代码以启动进度条***
使用 var client = new HttpClient())
{
// 启动所需的异步进程,在这种情况下它是GetStringAsync
text = await client.GetStringAsync( @ http://www.codeproject.com/跨度>);
}

// 控件在GetStringAsync完成时返回,
// **插入代码以停止进度条**
// 使用等待调用的结果执行某些操作
// 此处将TextBox文本设置为结果
.textBox.Text = text;
}


In my project I want to show the Marquee style progress bar.
where I had a form on which there is a toolbar containing a button.
On the click of that button I call a webservice.
Till webservice call returns I want to show the Marquee progress bar which is on modal dialog.

How I can achieve it by Tasks(TPL) or either way?
Please provide the code sample for it.

What I have tried:

CancellationToken cancelToken = new CancellationToken();
                Task task1 = Task.Factory.StartNew(() =>
                {
                    BaseParameters.ErrorBag.Clear();
                    if (ESignatureService.SignDocuments(documentIds, GlobalVariables.oLoginRO.PersonalSchluessel))
                        SaveAndPopulateDocuments();
                    breakFlag = false;
                }, cancelToken)
                .ContinueWith(t =>
                {
                    while (oi1ProgressStatus.PercentageComplete < 100)
                    {
                        oi1ProgressStatus.PercentageComplete++;
                        Thread.Sleep(100);
                        if (oi1ProgressStatus.PercentageComplete == 100)
                        {
                            oi1ProgressStatus.PercentageComplete = 0;
                        }
                    }
                }, TaskScheduler.Default);
                Task.WaitAny(task1);



I tried by this way but I am getting the following error.

"Controls that were created for a thread that can not be the parent of a control on a different thread."

The ProgressBar control[^] has built-in support for showing indeterminate progress - just set the Style property[^] to ProgressBarStyle.Marquee:
oi1ProgressStatus.Style = ProgressBarStyle.Marquee;

await Task.Run(() =>
{
    BaseParameters.ErrorBag.Clear();
    if (ESignatureService.SignDocuments(documentIds, GlobalVariables.oLoginRO.PersonalSchluessel))
        SaveAndPopulateDocuments();
    
    breakFlag = false;
});

oi1ProgressStatus.Style = ProgressBarStyle.Blocks;


NB: You can't update UI elements from a background thread, so you'll need to use Invoke to push the updates back onto the UI thread. If you use Task.WaitAny on the UI thread, you'll block the Invoke method, and cause a deadlock. Use async / await instead, which will keep the UI thread responsive whilst your background task is running.

If you can't use async / await, then use a BackgroundWorker[^] to perform your task.


Here's the basic idea, you may have to adapt it to your needs. Don't try to martial threads yourself, that is only necessary with legacy code. The async await keywords provide sufficient abstraction for you not to have to do that.

//This is the button click event handler
//note the async modifier
private async void ReadWebPageEventHandlerAsync(object sender, RoutedEventArgs e)
        {
            string text ;
			//***insert code to start the progress bar here***
            using (var client = new HttpClient())
            {
			     //start the required async process,  in this case it's GetStringAsync
                text = await client.GetStringAsync(@"http://www.codeproject.com/");
            }

            //control returns here when GetStringAsync finishes, 
			//**insert code to stop the progress bar here**
            //Do something with the result from the await call
             // here a TextBox text is set to the result
            this.textBox.Text = text;
        }