Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 表单级别的进度声明给出了一个异常_C#_Async Await - Fatal编程技术网

C# 表单级别的进度声明给出了一个异常

C# 表单级别的进度声明给出了一个异常,c#,async-await,C#,Async Await,在控制台应用程序中启动的WPF窗口中,我尝试在async await中使用IProgress: namespace Test { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Main : Window { // class level declaration Progress<string> Progress1;

在控制台应用程序中启动的WPF窗口中,我尝试在async await中使用IProgress:

namespace Test
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Main : Window
{
    // class level declaration
    Progress<string> Progress1;

    public Main()
    {
        InitializeComponent();

       // initialization of class level field
        Progress1 = new Progress<string>(value =>
        {
            Print(value);
        });
    }

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        Print("Start test");

        // local variable 
        Progress<string> Progress2 = new Progress<string>(value =>
        {
            Print(value);
        });

        // interface (normally Progress1/2 would be passed as a parameter)
        // Progress2 works fine, Progress1 gives an exception
        var progress = Progress1 as IProgress<string>;

        await Task.Run(() =>
        {
            for (int i = 0; i != 5; ++i)
            {
                if (progress != null) progress.Report("\nStage " + i);
                Thread.Sleep(1000);
            }
        });

        Print("\nCompleted.");
    }

    void Print(string text)
    {
        //Output is a WPF TextBlock
        Output.Inlines.Add(new Run(text) { Foreground = Brushes.Blue, FontWeight = FontWeights.Normal });
    }
}

在这种情况下,构造函数中的
Synchronization.Current==null
,它是
!=空
,例如加载的事件。如回答和评论中所述。

是的,请向Microsoft购买雪茄,以便将此诊断构建到Winforms中,因为否则这将是一个完全不可调试的问题,只是偶尔会导致代码崩溃

这是一个初始化顺序问题,它是由于您的进度变量初始化得太快造成的。请记住Progress类所做的工作,它知道如何运行在“正确线程”上传递的委托的目标。特别是,您希望它在UI线程上运行,以便安全地更新标签。Progress通过复制
SynchronizationContext.Current
,稍后使用它运行委托目标及其Post()方法来实现

问题是,
Current
属性还没有值。几微秒后,当表单基类构造函数运行时,就会发生这种情况。Progress复制了一个null,现在它唯一能做的就是在线程池线程上运行Post()方法目标。卡布姆

解决方法很简单:

Progress<string> Progress;

public Form1() {
    InitializeComponent();
    Progress  = new Progress<string>(value => {
        label.Text = value;
    });
}
进度;
公共表格1(){
初始化组件();
进度=新进度(值=>{
label.Text=值;
});
}

现在它在稍后初始化,Synchronization.Current有一个值。

是的,请向Microsoft购买一支雪茄,以便将此诊断构建到Winforms中,因为否则这将是一个完全不可调试的问题,只是偶尔会使代码崩溃

这是一个初始化顺序问题,它是由于您的进度变量初始化得太快造成的。请记住Progress类所做的工作,它知道如何运行在“正确线程”上传递的委托的目标。特别是,您希望它在UI线程上运行,以便安全地更新标签。Progress通过复制
SynchronizationContext.Current
,稍后使用它运行委托目标及其Post()方法来实现

问题是,
Current
属性还没有值。几微秒后,当表单基类构造函数运行时,就会发生这种情况。Progress复制了一个null,现在它唯一能做的就是在线程池线程上运行Post()方法目标。卡布姆

解决方法很简单:

Progress<string> Progress;

public Form1() {
    InitializeComponent();
    Progress  = new Progress<string>(value => {
        label.Text = value;
    });
}
进度;
公共表格1(){
初始化组件();
进度=新进度(值=>{
label.Text=值;
});
}


现在它在稍后初始化,Synchronization.Current有一个值。

无法重新编程。如果将声明移动到类范围,则会出现编译器错误。如果我将声明移动到类构造函数,它就可以正常工作。请发布导致问题的实际代码。我用准确的代码编辑了问题-它不可复制吗?不。它对我来说非常好。@StephenCleary它只能在启动WPF窗口的控制台应用程序中复制(请参阅我的编辑)。这是因为在启动应用程序的主循环
应用程序之前,您正在调用
Main.Main
。运行
。因此,正如Hans指出的,您的
SynchronizationContext.Current
null
。如果必须在控制台应用程序中宿主,则应在事件处理程序(如
窗口。加载的
)中进行初始化,而不是在构造函数中进行初始化。无法重新编程。如果将声明移动到类范围,则会出现编译器错误。如果我将声明移动到类构造函数,它就可以正常工作。请发布导致问题的实际代码。我用准确的代码编辑了问题-它不可复制吗?不。它对我来说非常好。@StephenCleary它只能在启动WPF窗口的控制台应用程序中复制(请参阅我的编辑)。这是因为在启动应用程序的主循环
应用程序之前,您正在调用
Main.Main
。运行
。因此,正如Hans指出的,您的
SynchronizationContext.Current
null
。如果您必须在控制台应用程序中宿主,那么您应该在事件处理程序(如
Window.Loaded
)而不是构造函数中进行初始化。起初我认为您完全正确。今晚我又尝试了一次,问题仍然存在,即使在构造函数中初始化(我使用wpf)。用精确的代码编辑问题。嗯,当你问WPF问题时,避免使用“形式”这个词。调试它,在语句上设置断点,并检查System.Threading.SynchronizationContext.Current的值。如果为null,那么我们需要大蒜和银弹。好的,接下来我要做的是在文本属性赋值上设置一个断点,并尝试理解调用堆栈调试器窗口。祝你好运,带大蒜来。我发现问题只发生在启动WPF窗口的控制台应用程序中(比较编辑)。发现这个有点晚了,对不起。线程在调度程序的
VerifyAccess
处失败。`@Gerard正如您在自己的
Main
方法中所看到的,在启动消息循环之前运行构造函数。在您已经有了消息循环之后,需要初始化
Progress
这意味着在构造函数完成后运行它。起初我认为您完全正确。今晚我又尝试了一次,问题仍然存在,即使在构造函数中初始化(我使用wpf)。用精确的代码编辑问题。嗯,当你问WPF问题时,避免使用“形式”这个词。调试它,在语句上设置断点,并检查System.Threading.SynchronizationContext.Current的值。如果为null,那么我们需要大蒜和银弹。好的,接下来我要做的是在文本属性赋值上设置一个断点,并尝试理解调用堆栈调试器窗口。祝我好运