动画“加载”表单的线程

时间:2015-02-04 14:11:51

标签: c# winforms

我有一个带动画的表单,我在做一些其他表单的请求时显示。我正在做一些研究如何在请求中显示这个动画形式,并想出这样做:

public partial class ProcessingForm : Form
{
    private static Thread processingFormThread;

    public ProcessingForm()
    {
        InitializeComponent();
    }

    public void StartThreadOnProcessingForm()
    {
        processingFormThread = new Thread(() => { new ProcessingForm().ShowDialog(); });
        processingFormThread.Start();
    }

    public void CloseThreadOnProcessingForm()
    {
        processingFormThread.Abort();
    }
}

现在,当我需要使用表格时,我这样做:

public void Foo()
{
    ProcessingForm pf = new ProcessingForm();
    pf.StartThreadOnProcessingForm();
    // some request/data actions
    Form requestForm;
    if (requestdata!= null)
    {
        requestForm = new requestForm(data);
        pf.CloseThreadOnProcessingForm();
        requestForm.Show();
        requestForm.SetDataForForm(requestdata);
    }
}

这就像一个非常简单的解决方案,但我在研究时没有看到类似的东西,所以感觉我做错了。我的问题是有更好的方法来做一个这样简单的事情吗?

3 个答案:

答案 0 :(得分:1)

解决此问题的一种方法是将Action传递给进度表单,并在进度表单的单独线程中执行该操作。操作完成后,关闭进度表单。

例如,您可以在进度表单中执行以下操作:

public partial class ProgressForm: Form
{
    public ProgressForm(Action action)
    {
        _action = action;
        InitializeComponent();
    }

    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);

        Task.Factory.StartNew(() =>
        {
            _action();
            _finished = true;
            BeginInvoke(new Action(Close));
        });
    }

    protected override void OnClosing(CancelEventArgs e)
    {
        // Prevent the user from closing the form until the action has completed.

        if (!_finished)
            e.Cancel = true;
    }

    private readonly Action _action;
    private volatile bool _finished;
}

然后,当您想要等待一个长动作完成时,您可以像这样使用进度表单(此示例显示在主窗体中单击按钮时的进度表单,并且该操作只是一个虚拟函数,睡几秒钟来模拟工作):

public partial class Form1: Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        using (var progress = new ProgressForm(action))
        {
            progress.ShowDialog();
        }
    }

    static void action()
    {
        Thread.Sleep(10000);
    }
}

答案 1 :(得分:0)

说实话,我并不真正理解你想要达到的目标,但有两个明显的问题:

  1. 开始一个新线程来调用ShowDialog毫无意义。使用ShowDialog而不是Show的关键是创建一个模态对话框,阻止执行(当前线程)直到对话框关闭。在新线程中执行此操作会使整个目的失败。

  2. 如Matthew Watson所述,Abort很糟糕。请参阅:What's wrong with using Thread.Abort()

  3. 我建议调用ProcessingForm非模态(Show),将其设为Topmost并禁用其他形式(无线程)。然后在后台Taskasync / await)中执行数据操作。任务完成后,关闭ProcessingForm并重新启用其他表单。

答案 2 :(得分:0)

如果我理解得很好,你想要一个能够理解何时自动显示和关闭的弹出窗口。

一个简单的解决方案是轮询一个名为' Busy'的静态属性。如果为true则调用表单上的Show,如果为false则调用hide。您可以通过将逻辑置于“忙碌”中来避免轮询。财产制定者。

在主应用程序中,您只需在长时间运行操作之前设置Popup.Busy = true,在完成操作时设置为false。

只需在新主题中启动弹出窗口。