显示来自其他线程的窗体

本文关键字:窗体 线程 其他 显示 | 更新日期: 2023-09-27 18:29:57

所以我有一个包含以下内容的静态类:

    public static void ShowErrorReport(Exception e, SqlCommand sqlc = null)
    {
        try
        {
            frmErrorReport frmER = new frmErrorReport(e, SqlCommand_: sqlc);
            frmER.ShowDialog();
            frmER.Dispose();
        }
        catch (Exception f)
        {
            Debug.Print(f.ToString());
        }
    }

我希望能够从一些在排队的后台工作程序中运行的与数据库相关的方法中使用它。问题是,这些方法有时不知道任何winforms对象,所以使用Invoke()是不可能的(据我所知)。

有没有其他方法可以从后台工作线程调用此过程,并确保在UI线程上创建表单?

或者,我会通过传递winforms对象来把这些数据库方法弄得一团糟吗(不期待这种可能性!)?

我对多线程很陌生。。。

感谢

显示来自其他线程的窗体

我希望能够从一些在排队的后台工作程序中运行的与数据库相关的方法中使用它。问题是,这些方法有时不知道任何winforms对象,所以使用Invoke()是不可能的(据我所知)。

如果您的后台代码需要与UI交互,则需要通过某种方式将其传递给UI以正确地与之对话。通常情况下,为了抽象这一点,您可以创建一个"交互服务",然后将其传递给您的类,然后该交互服务调用您需要的任何UI技术。

public BackgroundClass
{
    public BackgroundClass(IInteractionService interactionService)
    {
        _interactionService = interactionService;
    }
    private readonly IInteractionService _interactionService;
    public static void ShowErrorReport(Exception e, SqlCommand sqlc = null)
    {
        try
        {
            _interactionService.ShowErrorReportDialog(e, sqlc);
        }
        catch (Exception f)
        {
            Debug.Print(f.ToString());
        }
    }
}
public interface IInteractionService
{
    void ShowErrorReportDialog(Exception e, SqlCommand cmd);
}
public class WinFormsInteractionService : IInteractionService
{
    public WinFormsInteractionService()
        this(SynchronizationContext.Current)
    {
    }
    public WinFormsInteractionService(SynchronizationContext syncContext)
    {
        if(syncContext == null)
            throw new ArgumentNullException("syncContext");
        _syncContext = syncContext;
    }
    private readonly SynchronizationContext _syncContext;
    public void ShowErrorReportDialog(Exception e, SqlCommand cmd)
    {
        _syncContext.Send(s => 
        {
            using(frmErrorReport frmER = new frmErrorReport(e, SqlCommand_: cmd))
            {
                frmER.ShowDialog();
            }
        });
    }
}

如果您决定从Winforms切换到WPF,甚至切换到Console,那么BackgroundClass不需要进行任何更改,只需要为您使用的任何UI技术创建一个实现IInteractionService的新类。

public class ConsoleInteractionService : IInteractionService
{
    public WinFormsInteractionService()
    {
    }
    private readonly string _showErrorReportDialogFormatString = //...
    public void ShowErrorReportDialog(Exception e, SqlCommand cmd)
    {
        Console.WriteLine(_showErrorReportDialogFormatString, e, cmd);
        Console.WriteLine("Press enter to continue");
        Console.ReadLine();
    }
}