如何处理正在进行的任务

时间:2013-05-29 11:13:12

标签: c# winforms background task progress

在我的C#程序中有一个“登录”功能。当用户按下按钮时 - 程序使用给定的登录/通过信息使用POST URL登录某个网站并保存cookie。登录后的网页然后在我的程序中进一步处理。然后,结果显示给用户。

问题是 - 用户点击按钮的那一刻 - 整个程序挂起并等待直到完成上面的操作。那是大约3-5秒的不活动。

我想在此期间阻止用户输入并提示消息,例如“正在工作......”。其他没有办法告诉程序是否实际上正在处理某事。这就是我的意思:

enter image description here

我应该使用哪些技术来达到预期目标?

4 个答案:

答案 0 :(得分:4)

首先,你需要背景工作者。在BackgroundWorker Basics in C#

中有一个关于它的简单教程(带进度条)

答案 1 :(得分:3)

UI被阻止,因为您在UI线程中运行登录代码。为避免这种情况,您可以使用“BackgroundWorker”,或者如果您使用4或4.5 .NET,则可以使用“任务”将登录内容移动到另一个线程以避免UI阻塞。

如果Windows Forms和.NET 4+可能有效:

  private void button1_Click(object sender, EventArgs e)
    {
        progressBar1.Visible = true;
        Task.Factory.StartNew(Login)
            .ContinueWith(t => 
                { 
                    progressBar1.Visible = false; 
                }, TaskScheduler.FromCurrentSynchronizationContext());
    }

    private static void Login()
    {
        // should replace this with actual login stuff
        Thread.Sleep(TimeSpan.FromSeconds(3));
    }

它做什么,它将登录处理移动到另一个线程,因此不阻止UI线程。在盯着登录之前,它取消隐藏进度条,其样式设置为marque,登录完成后再次隐藏进度条。
只要UI未被阻止,用户就可以在登录期间输入/按下他想要的任何内容,因此解决方案是在登录前禁用所有控件或以单独的模式形式显示进度条,这样用户就不会看到应用程序在进度条形式关闭之前,我将被绞死并且无法进行任何输入。

更新:添加了具有单独进度表单的示例:

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

    private void button1_Click(object sender, EventArgs e)
    {
        MarqueeForm.DoWithProgress("Doing login", Login);
    }

    private static void Login()
    {
        Thread.Sleep(TimeSpan.FromSeconds(3));
    }
}

public class MarqueeForm : Form
{
    private Label label;

    public MarqueeForm()
    {
        var progressBar = new ProgressBar
                          {
                              Style = ProgressBarStyle.Marquee, 
                              Top = 20, 
                              Size = new Size(300, 15)
                          };

        Controls.Add(progressBar);

        label = new Label();
        Controls.Add(label);
    }

    public static void DoWithProgress(string title, Action action)
    {
        var form = new MarqueeForm
                   {
                       Size = new Size(310, 50),
                       StartPosition = FormStartPosition.CenterParent,
                       FormBorderStyle = FormBorderStyle.FixedDialog,
                       ControlBox = false,
                       label = { Text = title }
                   };

        form.Load += (sender, args) =>
            Task.Factory.StartNew(action)
                .ContinueWith(t => ((Form)sender).Close(),
                    TaskScheduler.FromCurrentSynchronizationContext());

        form.Show();
    }
}

答案 2 :(得分:0)

按下按钮时,您可以在显示“请稍候......”等消息时禁用按钮button1.Enable = false;。处理完成并显示结果时启用按钮。

答案 3 :(得分:0)

我想问题是关于Forms应用程序?

如果是这样,您可以将表单设置为“加载屏幕”,然后执行Application.Doevents();然后开始你的过程。完成后,您可以删除“加载屏幕”。