如何从MainWindow调用异步方法?

时间:2015-03-12 16:14:20

标签: c# wpf xaml async-await

所以我编写了一个快速async方法,将一些数据从Oracle数据库中导入DataTable。我怎么想在没有阻止UI线程的情况下从MainWindow()调用它? async / wait模型在那里确实没有多大意义。

    async Task<DataTable> AccessOracleAsync()
    {
        DataTable dt;
        using(OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["connStr"].ConnectionString))
        using (OracleCommand cmd = new OracleCommand(@"SELECT * FROM myTbl", conn))
        {
            await conn.OpenAsync();
            using (var reader = await cmd.ExecuteReaderAsync())
            {
                dt = new DataTable();
                dt.Load(reader);                        
            }

        }
        return dt;
    }

3 个答案:

答案 0 :(得分:9)

如果没有看到你的构造函数,很难说出什么可能会有意义?#34;那里。但是你在这里至少有几个选择。

选项#1:将调用放入构造函数中。

在这种情况下,您无法创建方法async,并且您肯定不希望继续执行在构造函数返回之前需要执行的任何操作。但是你仍然可以用async方法有效地完成C#所做的事情:

public MainWindow()
{
    InitializeComponent();

    AccessOracleAsync().ContinueWith(task => { /* do some other stuff */ },
        TaskScheduler.FromCurrentSynchronizationContext());
}

这将在UI线程上执行延续,就像您编写了await AccessOracleAsync(); /* do some other stuff */一样。根据需要在continuation方法中添加异常处理(即检查task对象并正确处理)。

选项#2:将电话放在其他地方。

建议您使用Loaded事件,您可以这样做。这可能看起来像这样:

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    await AccessOracleAsync();

    // do some other stuff
}

请注意,如果后者看起来合适,恕我直言,它更可取。它允许C#编译器为您做繁重的工作,包括处理异常(您可以将调用包裹在try / catch中,所有内容&#34;只是工作&#34;)。< / p>

答案 1 :(得分:2)

尝试为Laoded事件创建处理程序,将其标记为async并从那里调用AccessOracleAsync方法。

答案 2 :(得分:1)

我刚做完这件事,男孩真是个挣扎!您不能按照其他答案中的建议调用您的方法,因为调用方法或构造函数将结束,任务将丢失。

我做了两件事

1:绑定窗口加载的事件,而不是在构造函数

中执行

2:如果你想在后台进程中运行,你必须调用Task.Run,​​无论你的方法是否异步

例如

    public async void Window_Loaded(object sender, RoutedEventArgs e)
    {
        Task.Run(()=>this.AccessOracleAsync().ContinueWith(function to deal with results));
    }

此外,如果您需要返回前台线程以使用结果更新UI,您将需要启用集合以确保线程安全

    public MainVM()
    {
        this.results= new ObservableCollection<resultType>();
        BindingOperations.EnableCollectionSynchronization(results, _itemsLock);
    }
    private static object _itemsLock = new object();
    public ObservableCollection<resultType> results{ get; set; }