简体   繁体   English

显示表单(对话框)而不阻塞当前线程(进度条示例)

[英]show a form(dialog) without blocking the current thread (progressbar example)

I'm trying to create a ProgressBar form that uses a BackgroundWorker to execute an action on a different thread while displaying a progress bar. 我正在尝试创建一个ProgressBar窗体,该窗体使用BackgroundWorker在显示进度条的同时在另一个线程上执行操作。

At the moment my ProgressBar class contains a ProgressBarControl and here's how the code looks like: 目前,我的ProgressBar类包含一个ProgressBarControl,代码如下所示:

public partial class QTProgressBar : DevExpress.XtraEditors.XtraForm
{
    private BackgroundWorker m_backgroundWorker;
    private AutoResetEvent m_resetEvent;

    public QTProgressBar()
    {
        InitializeComponent();

        InitializeProgressBar();

        m_backgroundWorker = new BackgroundWorker();
        m_backgroundWorker.WorkerReportsProgress = true;
        m_backgroundWorker.WorkerSupportsCancellation = true;
        m_backgroundWorker.DoWork += new DoWorkEventHandler(m_backgroundWorker_DoWork);
        m_backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(m_backgroundWorker_ProgressChanged);
        m_backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_backgroundWorker_RunWorkerCompleted);
        m_resetEvent = new AutoResetEvent(false);
    }

    void m_backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        m_resetEvent.Reset();

        CloseProgressBar();
    }

    void CloseProgressBar()
    {
        if (InvokeRequired)
        {
            Invoke( new MethodInvoker(CloseProgressBar));
            return;
        }
        this.Close();
    }

    void m_backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        Action operation = e.Argument as Action;
        operation();
    }

    public void StartAsyncTask(Action operation)
    {
        m_resetEvent.Set();
        m_backgroundWorker.RunWorkerAsync(operation);
    }
}

For now, when i want to show a popup i do this: 现在,当我想显示弹出窗口时,请执行以下操作:

QTProgressBar op = new QTProgressBar();
op.StartAsyncTask(() => LongDurationOperation(5, 5));
op.ShowDialog(); // i would like to move this inside the ProgressBar class.
//Thread gets blocked here until operation finishes. 

Where LongDurationOperation is : LongDurationOperation在哪里:

public void LongDurationOperation(int n, int m)
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            Thread.Sleep(100);
        }
    }
}

I would like to avoid blocking any thread that calls the 我想避免阻塞任何调用该线程的线程

ShowDialog() 

method of the progressBar class. progressBar类的方法。 If i move this anywhere inside the ProgressBar class thread gets blocked and operation does not execute. 如果我将其移到ProgressBar类线程内的任何地方,将被阻塞并且操作将无法执行。

Is it possbile to avoid blocking the thread that calls the Showdialog() method? 是否有可能避免阻塞调用Showdialog()方法的线程?

Also, can you give me some hints on how this class can be improved? 另外,您能给我一些关于如何改进此类的提示吗?

Thanks a lot. 非常感谢。

There is two different call that exist in a form: 表单中存在两种不同的调用:

myForm.ShowDialog();

Is the modal version that block the thread calling it. 是阻止线程调用它的模式版本。 It is used for popup that must prevent other action from taking place (like save dialog). 它用于必须阻止其他动作发生的弹出窗口(如“保存”对话框)。

myForm.Show(IWin32Window owner);

Is the non-modal version. 是非模式版本。 It doesn't block the current thread, but doesn't return any result. 它不会阻止当前线程,但是不会返回任何结果。 However, you must pass it the owner, often like this: 但是,您必须像通常这样将其传递给所有者:

myForm.Show(this);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM