首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EventToCommand异步?

EventToCommand异步?
EN

Stack Overflow用户
提问于 2015-10-13 05:42:37
回答 4查看 274关注 0票数 0

我正在编写一个WPF程序,其中我使用EventToCommand来处理第三方控件中的事件,并将它们连接到ICommands。我的视图模型方法都是异步的,我遇到的问题是事件没有等待处理程序完成。在WPF中说明问题有点长,但我在下面的小控制台应用程序中总结了这个问题。

我的主要问题是,是否有一个EventToCommand的实现允许我使用异步处理程序?是的,我做了谷歌,没有发现任何东西。mvvm文档这里没有提到异步。

我对完成任务的任何工作都持开放态度。注意,在下面的代码中,我使用了"ButtonClick“的名称,这可能会导致您问为什么我不只是绑定到命令.。这是一个错误的命名选择的例子对不起。在我的WPF应用程序中,我正在处理没有命令的事件。

代码语言:javascript
复制
class Program
{
    public event EventHandler ButtonClickEvent;

    static void Main(string[] args)
    {
        Console.WriteLine("Program");
        var p = new Program();
    }

    public Program()
    { 
        ButtonClickEvent += ButtonClickEventHandler;
        Console.WriteLine("Start fire event");
        ButtonClickEvent(this, new EventArgs()); // In WPF app this event is handled by EventToCommand, which executes an ICommand
        Console.WriteLine("End fire event");
        Console.Write("Press any key...");
        Console.ReadKey();

        // Output
        // Start fire event
        // Start GetStringAsync
        // End fire event            <-- not waiting
        // End GetStringAsync
    }

    // In WPF app this method is wired up to a DelegateCommand
    public async void ButtonClickEventHandler(object sender, EventArgs e)
    {
        await DownloadStuffAsync();
    }

    public async Task DownloadStuffAsync()
    {
        Console.WriteLine("Start GetStringAsync");
        string page = await new HttpClient().GetStringAsync("http://www.ibm.com");
        Console.WriteLine("End GetStringAsync");
    }
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-10-13 06:00:06

EventHandlers不支持异步方法。您需要一些Task返回方法作为解决办法,并等待调用事件的Task

您可以使用Stephen关于这个主题的文章中解释过的这里的延迟。还有其他解决方案,比如重写SynchronizationContext,但是使用上面所示的更好的解决方案。

票数 1
EN

Stack Overflow用户

发布于 2015-10-13 12:00:28

我遇到的问题是事件没有等待处理程序完成。 我的主要问题是,是否有一个EventToCommand的实现允许我使用异步处理程序?

好吧,从第三方控制的角度看问题。它引发了一个类似于这样的事件:

代码语言:javascript
复制
void ControlEvent(object sender, ControlEventArgs args);

当委托返回时,它就完成了。事件处理程序签名返回void,所有参数都是从控件传递给事件处理程序的数据。没有“回传通讯”。委托没有办法告诉第三方控制:“我还没有完全完成;我只是返回释放线程,因为我是异步的;我有更多的代码要稍后执行,然后我将真正完成。”

因此,简而言之,您想要做的事情可能需要对第三方控件进行非琐碎的更改。有尝试强制异步代码同步完成的各种黑客攻击 (正如我在最近的一篇MSDN文章中所描述的),但是它们都没有很好的工作。正如Sriram所说,一个更好的解决方案是将第三方控件更改为使用延期;我在我的博客中描述了推迟执行的一项可能措施。然而,对于第三方控制而言,这将是一个重要的改变,他们可能不愿意这样做。

票数 1
EN

Stack Overflow用户

发布于 2015-10-13 06:16:12

我在WPF的评论中尝试了Sriram给出的链接解决方案,它确实有效。

我的ViewModel

代码语言:javascript
复制
public class ViewModel
{
    public ICommand DoSomethingCommand { get; set; }
    public ViewModel()
    {
        DoSomethingCommand = new RelayCommand(DoSomething);
    }

    private async void DoSomething()
    {
        await DownloadStuffAsync();
        Debug.WriteLine("Button Call Completed");
    }
    public async Task DownloadStuffAsync()
    {
        Debug.WriteLine("Start GetStringAsync");
        await Task.Run(() =>
        {
            Debug.WriteLine("Thread sleeping");
            Thread.Sleep(5000);
        }).ConfigureAwait(false);
        string page = await new HttpClient().GetStringAsync("http://www.ibm.com").ConfigureAwait(false);
        Debug.WriteLine("End GetStringAsync");
    }
}

我的观点

代码语言:javascript
复制
<StackPanel>
    <Button Content="Do Something" Margin="0,2,2,2" Command="{Binding DoSomethingCommand}"/>
</StackPanel>

和调试窗口上的输出。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33094950

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档