如何异步显示隐藏忙图像

时间:2014-02-14 08:55:05

标签: asynchronous c#-2.0

当我做长时间运行的任务时,我想显示忙碌的图像并在完成工作时隐藏忙碌的图像。

private void btnSave_Click(object sender, EventArgs e)
        {
            string strRating = "";
            Messages oErrMsg = Messages.Instance;
            FeedBack oFeedBack = new FeedBack();
            picbox.Visible = true;

            Application.DoEvents();

            if (cboRating.Text.Trim() == "--Select--")
            {
                strRating = "";
            }
            else
            {
                strRating = cboRating.Text.Trim();
            }

            try
            {

                oErrMsg = oFeedBack.UpdateFeedBack(JobID, strRating, txtComments.Text.Trim(), AccountRef, PartNumber);
                if (!oErrMsg.IsError)
                {
                    picbox.Visible = false;
                    comments _cmm = new comments();
                    _cmm.Comments = txtComments.Text;
                    _cmm.Rating = strRating;
                    _cmm.Row = this.Row;
                    _cmm.Col = this.Col;
                    OnValueChanged(_cmm);

                    DialogResult = DialogResult.OK;
                    this.Close();
                }
                else
                {
                    picbox.Visible = false;
                    MessageBox.Show(oErrMsg.Message);
                }
            }
            catch (Exception ex)
            {
                picbox.Visible = false;
            MessageBox.Show(ex.Message.ToString());
        }
    }

picbox.Visible = true; 

picbox有忙图像,但问题是图像没有显示,因为我显示忙,然后长时间运行操作开始。所以指导我如何异步显示繁忙的图像并在完成工作时隐藏。感谢

2 个答案:

答案 0 :(得分:1)

托马斯,

请考虑使用BackgroundWorker(http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.80).aspx)。

自2.0版以来,它一直存在于.NET框架中。

答案 1 :(得分:1)

正如@Piotr所建议的那样,您可以使用BackgroundWorker线程来实现这一目标。

作为你的代码无法工作的原因,btn点击处理程序在UI线程上运行,你碰巧在同一个(UI)线程中完成所有工作,这意味着UI线程无法在Busy中绘制更改指示器。

虽然Application.DoEvents()有助于强制重绘,但应该避免它,并且正确的方法是将所有工作委托给后台线程(您也可以使用ThreadPool.QueueUserWorkItem)并封送所有对UI对象的更改使用Control.BeginInvoke / Control.Invoke。

将属性添加到UI线程

因为,UI对象的任何更改只能在UI线程上完成,您必须使用Control.Invoke等来封送此类更新。

BackgrounWorker类通过提供不同的事件处理程序来封装此编组。从内存中,我精简了ProgressChanged和Completed处理程序在UI线程上调用。因此,您可以安全地更新这些处理程序中的UI控件,并在DoWork处理程序中执行耗时的工作。

更新:以下是DoEvents is Evil

的原因