当多次点击按钮时,如何防止应用程序挂起?

3

我的应用程序中有一个扫描按钮,用户可以点击该按钮扫描图像以在应用程序中进行预览。当用户点击时,通常会显示“正在准备扫描”的消息,并在扫描完成100%时消失。

扫描工作正常。但是,如果我在其工作时多次按下扫描按钮来进行压力测试,则应用程序会完全挂起,消息仍然停留在那里,我不得不重新启动整个应用程序。

代码:这只是一个小部分。

private void ScanStripButton_Click(object sender, EventArgs e)
{
    if (SCAN_INTO_BATCH)
    {
        GENERATE_BATCH_FOLDER = true;
        StartTwainScan();
    }
}

有什么办法可以防止这个问题发生吗?感谢帮助。
编辑:
public void StartTwainScan()
{
    Boolean EnableUI = false;
    Boolean ADF = false;
    Boolean EnableDuplex = false;

    if (Properties.Settings.Default.TwainShow.Equals("1"))
    {
        EnableUI = true;
    }

    if (Properties.Settings.Default.ScanType.Equals("2"))
    {
        ADF = true;
    }

    if (Properties.Settings.Default.DuplexEnable.Equals("1"))
    {
        EnableDuplex = true;
    }

    var rs = new ResolutionSettings
    {
        Dpi = GetResolution(),
        ColourSetting = GetColorType()
    };

    var pg = new PageSettings()
    {
        Size = GetPageSize()
    };


    var settings = new ScanSettings
    {
        UseDocumentFeeder = ADF,
        ShowTwainUI = EnableUI,
        ShowProgressIndicatorUI = true,
        UseDuplex = EnableDuplex,
        Resolution = rs,
        Page = pg
    };

    try
    {
        TwainHandler.StartScanning(settings);
    }
    catch (TwainException ex)
    {
        MessageBox.Show(ex.Message);
        //Enabled = true;
        //BringToFront();
    }
}

1
使用async/await进行包装,或者防止多次点击。 - Z.R.T.
@Z.R.T. 你能再澄清一下吗? - TomCold
2个回答

4

这不会是正确答案,但你没有展示足够的代码来给你正确的代码。它应该指引你朝正确的方向发展。

private void ScanStripButton_Click(object sender, EventArgs e)
{
    ScanStripButton.Enabled = false;
    if (SCAN_INTO_BATCH)
    {
        GENERATE_BATCH_FOLDER = true;
        StartTwainScan();
    }
    ScanStripButton.Enabled = true;
}

基本上,您需要在扫描开始时禁用按钮,在扫描结束后启用它。

这正是我想要实现的。我会尝试一下。 - TomCold
1
简单的答案通常是最好的。 - Enigmativity
@Z.R.T. - 你的try/finally代码块有问题。它会吞噬错误,这是应该避免的。如果扫描抛出异常,那么只应该捕获该异常。 - Enigmativity
@Z.R.T. - 你使用的 private bool clicked 也不是很好 - 这样会加入一些不必要的代码,从而增加编程错误的机会。而 button.Enabled 已经存在并且更好用。 - Enigmativity
1
如果我的StartTwain方法已经有一个try catch,就像我编辑过的帖子中所示,该怎么办? - TomCold
显示剩余9条评论

2
private async void ScanStripButton_Click(object sender, EventArgs e)
{
    await Task.Run(() =>
    {
        if (SCAN_INTO_BATCH)
        {
            GENERATE_BATCH_FOLDER = true;
            StartTwainScan();
        }
    });
}

or 

private bool clicked = false;
private void ScanStripButton_Click(object sender, EventArgs e)
{
    try
    {
        if(clicked)
            return;

        clicked = true;
        if (SCAN_INTO_BATCH)
        {
            GENERATE_BATCH_FOLDER = true;
            StartTwainScan();
        }
    }
    finally
    {
        clicked = false;
    }
}

我还没有尝试你的解决方案,因为上面标记的解决方案更简单,不过还是谢谢你。 - TomCold
你能详细解释一下第二个解决方案吗? - TomCold
第一种解决方案可能会遇到Twain驱动程序使用公寓线程模型的问题。 第二个解决方案是冗余的,因为ScanStripButton.Enabled可以做与private bool clicked相同的事情,但它提供了更加用户友好的行为。 try/finally还会隐藏所有错误-这是不好的。 你应该只捕获具体的异常。 - Enigmativity

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接