简体   繁体   English

Task.Run(()=> Method()); 没有运行该方法?

[英]Task.Run(() => Method()); doesn't run the method?

In my WPF application: 在我的WPF应用程序中:

using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
using System.Diagnostics;

namespace CloudKey
{
/// <summary>
/// Interaction logic for Page1.xaml
/// </summary>
public partial class Page1 : Page
{
    public Page1()
    {
        InitializeComponent();

        AuthText.Visibility = Visibility.Hidden;

    }
    private async void button_Click(object sender, RoutedEventArgs e)
    {

        AuthText.Visibility = Visibility.Visible;
        await Task.Run(() => Authenticate());
        Task.Factory.StartNew(() => Authenticate());
        Task.Run(() => Authenticate());
        Authenticate();
    }
    void Authenticate()
    {
        //Do Stuff
    }
  }
}

No matter which way I try to call Authenticate with Tasks it just doesn't run. 无论我尝试以哪种方式调用“通过Tasks进行Authenticate ,它都不会运行。 Am I using Task wrong? 我使用Task错误?

Using await (and async) causes an exception to be thrown: 使用await(和async)会引发异常:

System.InvalidOperationException was unhandled Message: An unhandled exception of type 'System.InvalidOperationException' occurred in mscorlib.dll Additional information: The calling thread cannot access this object because a different thread owns it. 未处理System.InvalidOperationException消息:mscorlib.dll中发生了'System.InvalidOperationException'类型的未处理异常。其他信息:调用线程无法访问此对象,因为其他线程拥有它。

Using just Task.Run or Task.Factory.StartNew causes the Authenticate method not to be run at all. 仅使用Task.Run或Task.Factory.StartNew会导致完全不执行Authenticate方法。 If I add a breakpoint to the Authenticate method it isn't reached. 如果我将断点添加到Authenticate方法中,则无法实现。

Just calling the method with Authenticate() runs the entire method without issue, but it freezes the UI making "AuthText.Visibility = Visibility.Visible;" 只需使用Authenticate()调用该方法即可运行整个方法,而不会出现问题,但是它将冻结UI,使之成为“ AuthText.Visibility = Visibility.Visible;”。 useless. 无用。

To be honest, I really just want the UI to update with the message "Authenticating..." and THEN run everything in the method when I click the button. 老实说,我真的只希望UI更新消息“ Authenticating ...”,然后在单击按钮时运行方法中的所有内容。 Is there perhaps an easier way to do that? 也许有更简单的方法做到这一点?

THIS IS THE WORKING CODE FOR REFERENCE: 这是参考的工作代码:

using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;
using System.Diagnostics;
using System.Threading.Tasks;

namespace CloudKey
{
/// <summary>
/// Interaction logic for Page1.xaml
/// </summary>
public partial class Page1 : Page
{
    public Page1()
    {
        InitializeComponent();

        //private void PasswordBox_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { button_Click } }
        AuthText.Visibility = Visibility.Hidden;

    }
    private void button_Click(object sender, RoutedEventArgs e) //ON CONTINUE BUTTON CLICK
    {
        AuthText.Visibility = Visibility.Visible;
        Task.Run(() => Authenticate());
    }
    void Authenticate()
    {
        Dispatcher.Invoke(
        () =>
        {
          //ALL MY CODE HERE;
        });
      }
    }
  }

The issue is that you're not waiting for the asynchronous task to complete, so it appears like "nothing happens" - when in fact something does happen. 问题是您不等待异步任务完成,因此看起来好像“什么都没有发生”-实际上确实发生了。 When you invoke either Task.Run or Task.Factory.StartNew you're essentially performaing a fire-and-forget, unless you correctly handle the Task . 当您调用Task.RunTask.Factory.StartNew ,除非您正确处理Task ,否则实际上就是在执行即Task.RunTask.Factory.StartNew

private async void button_Click(object sender, RoutedEventArgs e)
{
    await Task.Run(() => Authenticate()); // Stuff happens
}

void Authenticate()
{
    // DO STUFF
}

In the example above adding the keyword async to the event handler allows the method to utilize the await keyword. 在上面的示例中,将关键字async添加到事件处理程序允许该方法利用await关键字。 The await keyword is where all the magic really occurs...but it will then work as you'd expect, ie; await关键字是所有魔术真正发生的地方……但是它将按您期望的那样工作,即; "Stuff happens". “事情发生了”。

When I do beat Stephen Cleary to these answers I usually point people to his blogs, this one in particular should help clarify this for you. 当我击败斯蒂芬·克雷蒂(Stephen Cleary)时,通常会向人们指向他的博客, 这一博客尤其应为您澄清这一点。

Note 注意

Writing an async void is strongly discouraged! 强烈建议不要编写async void The only exception is in your example where you are applying it to an event handler. 唯一的例外是在示例中将其应用于事件处理程序。 Finally, when using Task , and Task<T> with the async / await keywords - do so through the entire stack. 最后,当使用TaskTask<T>以及async / await关键字时,请在整个堆栈中使用。 I would change your Authenticate method to return a Task for example, such that it can be awaited. 我会更改您的Authenticate方法以返回一个Task ,例如,可以等待它。 Try invoking Task.Run at the lowest level possible. 尝试调用Task.Run尽可能最低的级别。

private async void button_Click(object sender, RoutedEventArgs e)
{
    await Authenticate(); // Stuff happens
}

Task Authenticate()
{
    return _authModule.Authenticate();
}

Update 更新资料

Based on your comments, do the following: 根据您的评论,执行以下操作:

private void button_Click(object sender, RoutedEventArgs e)
{
    bool authenticated = false;
    try
    {
        AuthText = "Authenticating...";
        authenticated = Authenticate(); // Stuff happens
    }
    finally
    {
        AuthText = authenticated ? "Authenticated" : "Oops!";
    }
}

bool Authenticate()
{
    // Return if auth was successful
}

When you modify UI stuff in a new thread then you need to use Dispatcher.Invoke or you can use InvokeAsync 在新线程中修改UI内容时,您需要使用Dispatcher.Invoke ,也可以使用InvokeAsync

    private void Button_Click( object sender, RoutedEventArgs e ) { Task.Run( () => Authenticate() ); }

    public void Authenticate()
    {
        Dispatcher.Invoke(
            () =>
            {
                ClickButton.Content = "Text Changed";
            } );
    }

By using Dispatcher You are telling WPF that run this code block on main thread which has access to update your GUI controls. 通过使用Dispatcher您正在告诉WPF在有权更新您的GUI控件的主线程上运行此代码块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM