我应该如何从后台线程请求用户输入

本文关键字:请求 用户 输入 线程 后台 我应该 | 更新日期: 2023-09-27 18:30:05

我正在使用外部库加载一个庞大而复杂的文件。对这个库的调用相当复杂,所以我将它们封装在几个静态助手方法中,这些方法可以很好地处理缓存等。然后,这些方法在后台使用Tasks运行。

在加载过程中,库在某些情况下会抛出异常,指出文件块的格式不正确,因此无法解析。这些异常被认为是"安全的",如果它们被吞下,库将跳过坏块,并愉快地继续解析文件的其余部分。

当这种情况发生时,我需要向用户显示一个对话框,询问是否应该中止文件导入。这可以很好地工作如下:

public static class MyBigFileLoadMethods {
    // private fields for locking, caching, etc.
    public static Load(string filePath, bool cache = true) {
        // validation etc.
        try {
            var data = LoadMethodInDll(filePath);  
        } catch (BadBlockException) {
            if (MessageBox.Show("boom.  continue anyway?") == DialogResult.Yes) {
                // call appropriate dll methods to ignore exception and continue loading
            } else {
                throw;
            }
        }
    }
}

从一个设计为在后台运行的方法中调用MessageBox.Show()感觉非常错误,但我还没有想出一个更好的方法,它不涉及太多的封送和调用,以至于代码变得很难阅读。有没有一种更干净的方法来做这件事,或者有一种更好的方法来设计我的装载过程?

我应该如何从后台线程请求用户输入

库实现这一点的适当方式是通过某种回调。最简单的实现是委托返回一个bool,指示是否应该继续处理。一种更丰富但复杂的方式是使用各种方法实现的策略接口,指示是否继续、中止、重试等。

然后,UI代码提供回调,以适当的方式向用户显示消息。加载库的代码如下所示:

public static class MyBigFileLoadMethods {
    // private fields for locking, caching, etc.
    public static void Load(string filePath, Func<Exception, bool> continueOnException = null, bool cache = true) {
        // validation etc.
        try {
            var data = LoadMethodInDll(filePath);  
        } catch (BadBlockException e) {
            if (continueOnException != null && continueOnException(e))  {
                // call appropriate dll methods to ignore exception and continue loading
            } else {
                throw;
            }
        }
    }
}

然后,在您的UI代码中,您将希望封送回UI线程。它看起来像这样:

MyBigFileLoadMethods.Load("C:'path'to'data", ShowError);
private bool ShowError(Exception e)
{
    if (this.InvokeRequired)
    {
        return (bool)this.Invoke(new Func<Exception, bool>(ShowError), e);
    }
    return MessageBox.Show(string.Format("boom: {0}. continue anyway?", e.Message)) == DialogResult.Yes;
}