调用异步回调但有时不执行

时间:2016-07-14 19:57:19

标签: c# wcf asynchronous

Silverlight项目。

在我后面的View代码中,我在View Model中调用一个方法来获取值。

 public MyViewModel ViewModel
    {
        get
        {
            if (this.viewModel == null)
                this.viewModel = new MyViewModel();
            return this.viewModel;
        }
        set
        {
            if (this.viewModel != value)
            {
                this.viewModel = value;
            }
        }
    }

但是不会调用异步回调。有时它会被延迟调用。因此,我得到的值为1900-01-01 00:00:00.000,而不是正确的日期时间。

DateTime value;
public void GetDateTime()
    {
        var proxy = new WcfClient();
        proxy.GetCurrentDateTimeCompleted -= ProxyGetCurrentDateTimeCompleted;
        proxy.GetCurrentDateTimeCompleted += ProxyGetCurrentDateTimeCompleted;
        proxy.GetCurrentDateTimeAsync();
    }

    private void ProxyGetCurrentDateTimeCompleted(object sender, GetCurrentDateTimeCompletedEventArgs args)
    {
        try
        {
            value = args.Result;

在后面的代码中调用它。

this.viewModel.GetDateTime();

更新1

评论结束后,我补充了一些解释。视图有一个复选框。如果我单击它或取消选中它,将弹出一个带有是/否按钮的消息框。无论您选择是或否,我都会在MessageBoxYesNoSelection_Closed事件中记录日期和时间。事件方法仍在代码背后。

复选框部分代码为:

if (clickedCheckBox != null)
{
    var msgBoxControl = new MessageBoxControl();
    msgBoxControl.Closed -= MessageBoxYesNoSelection_Closed;
    msgBoxControl.Closed += MessageBoxYesNoSelection_Closed;

    if (clickedCheckBox.IsChecked == true)
    {
        var curDateTime = this.ViewModel.value;// 1900-01-01 00:00:00.000

MessageBoxYesNoSelection_Closed内,我们得到了值。

this.ViewModel.GetDateTime();// WCF async call
this.ViewModel.UpdateValue(value); // another WCF async call, need value from GetDateTime() method's return result.
this.ViewModel.UpdateAnotherValue(value, user); // third WCF async call

我发现有时异步回调虽然被调用但不会被执行。

1 个答案:

答案 0 :(得分:3)

我猜您遇到了SQL Developer, SQL Server and the ampersand,因为您没有等待elem2调用,因此在大多数情况下,设置值(this.ViewModel.GetDateTime())的回调尚未被调用在使用下一个语句(ProxyGetCurrentDateTimeCompleted)中的值之前。

最简单的解决方案是使用this.ViewModel.UpdateValue(value)&如race conditionhere所述async

如果你不能这样做,另一个解决方案是将依赖于值的代码移动到回调方法中。

更新1

有可能使用await&使用Silverlight 4和.NET Framework 4.0 async。有关详细信息,请参阅here。但是,此方法至少需要Visual Studio 2012,因此如果您无法切换到较新的Visual Studio版本,这将不适合您。

在这种情况下,想法是将依赖于值的代码移动到回调方法中。因此,首先您只需拨打await

GetDateTime()

然后你将调用回调方法中的其他方法:

this.ViewModel.GetDateTime(); // WCF async call

更新2

在您上次发表评论后,我建议您重新构建应用程序,以便您可以使用第一次更新中显示的方法。在后面的代码中存储数据和视图模型似乎有点奇怪。但是,如果您需要快速解决方案,还可以等待回调手动设置值。请参阅以下代码作为示例,以帮助您入门:

private void ProxyGetCurrentDateTimeCompleted(object sender, GetCurrentDateTimeCompletedEventArgs args)
{
    value = args.Result;
    UpdateValue(value); // another WCF async call, need value from GetDateTime()
    UpdateAnotherValue(value, user); // third WCF async call
}

现在你可以添加一个等待直到设置值的循环:

DateTime value;
bool wcfCallInProgress;
public void GetDateTime()
{
    var proxy = new WcfClient();
    proxy.GetCurrentDateTimeCompleted -= ProxyGetCurrentDateTimeCompleted;
    proxy.GetCurrentDateTimeCompleted += ProxyGetCurrentDateTimeCompleted;
    wcfCallInProgress = true;
    proxy.GetCurrentDateTimeAsync();
}

private void ProxyGetCurrentDateTimeCompleted(object sender, GetCurrentDateTimeCompletedEventArgs args)
{
    value = args.Result;
    wcfCallInProgress = false;
}

如果您使用此方法,则必须确保超时和异常不会成为问题。否则你可能会以无限循环结束。