Winforms构造函数时序错误

本文关键字:错误 构造函数 Winforms | 更新日期: 2023-09-27 18:36:40

我有以下Winforms层次结构。

Form ==> AForm ==> BForm

并且在 FormA 中定义了一个可空的成员int? X;。而在FormB中,有以下代码。

public partial class FormA: Form
{
    public int? X { get; set; }
    public FormA(int? x) { X = x }
....
public partial class FormB: FormA, IFormAView
{
    public FormB()
    {
        AsyncCall(() => 
        {
            int z = X ?? 0;
            System.Diagnostics.Debug.WriteLine("X: " + X.ToString() + " z: " + z.ToString());
            return z;
        }
public static T GetForm<T>(int? x)
{
    T form = new T();
    form.X = x;
    form.Show();
}
GetForm<FormB>(100);

X从未被分配为 null 或零。我正在尝试关闭并打开表单FormB。有时z为零(可能每 10 次一次)。我设置了一个条件中断,当z==0在行return z时中断。

命中断点时。调试写入

    X:  z: 0

甚至调试也显示 FormA:X 不为零。

Winforms构造函数时序错误

您正在另一个线程上调用代码来测试 X(使用 AsyncCall 和"X ??"),该代码可能会也可能不会在 FormA 构造函数中分配 X 之前或之后运行。

也就是说,如果您停止使用AsyncCall,则应获得一致的结果。

在 FormA 中,X 是一个可为 Null 的 int 属性,默认为 null 。 您永远不会从public FormB()构造函数调用public FormA(int? x)基构造函数,因此 X 永远不会设置为其他任何内容。

由于在调用 FormB 的构造函数(调用 AsyncCall)后设置 X 的值,因此会遇到计时问题,因为 AsyncCall 可能会在 GetForm 函数中设置form.X = x;之前或之后强制。

如果您希望 AsyncCall 仍然是 AsyncCall,则应将 FormB() 的构造函数更新为如下所示:

public FormB(int? x) : base(x){ //...

然后按如下方式更新 GetForm(注意 where 子句,这让我们知道 T 至少是从 FromA 派生的,所以它有一个接受 int 的构造函数?

public static T GetForm<T>(int? x) where T : FormA
{
     T form = new T(x);
     form.Show();
}