4

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

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

我想在那段时间阻止用户输入并提示消息,例如“工作......”。否则,无法判断该程序是否真的在做某事。这就是我的意思:

在此处输入图像描述

我应该使用什么技术来实现预期的目标?

4

3 回答 3

2

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

如果 Windows 窗体和 .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();
    }
}
于 2013-05-29T11:27:06.660 回答
0

我想问题是关于表单应用程序的?

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

于 2013-05-29T11:23:48.193 回答
0

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

于 2013-05-29T11:19:05.050 回答