异步WCF服务调用阻止UI线程 [英] Async WCF service call blocking UI thread

查看:88
本文介绍了异步WCF服务调用阻止UI线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在使用WPF应用程序进行后台调用时遇到了麻烦.看来,在较旧的计算机上(我们最常在具有2GB RAM的Windows 7计算机上看到它),我们的Web服务调用阻止UI 直到完成.特别是对于一个呼叫,这是一个巨大的问题,因为它可能需要五分钟才能完成.较新的计算机似乎可以很好地处理它.

We are having trouble with a background call from our WPF application. Seemingly, on older computers (we have seen it most often on Windows 7 machines with 2GB of RAM or so) our web service call blocks the UI until it completes. For one call in particular, that is a huge problem because it can take five minutes to complete. Newer computers seem to handle it fine.

我们不在乎通话所花费的时间;我们只关心它不会阻塞UI.我看不到我们在做任何错误的事情.

We don't care about the amount of time the call takes; we only care about it not blocking the UI. I do not see anything we are doing wrong off-hand.

我们是在做错什么,还是Windows 7在2GB RAM上发生了什么?在这样的机器上,有什么方法可以解决吗?

Are we doing something wrong, or is it something with Windows 7 on 2GB of RAM? Is theere any way to work around it on such a machine?

我们是否必须达到编写自定义 TaskScheduler 的级别,以确保不使用UI线程?我当然希望不会.

Do we have to go to the level of writing a custom TaskScheduler to make sure the UI thread does not get used? I sure hope not.

非常感谢任何输入.提前致谢.请参见下面的代码示例.

Any input at all is greatly appreciated. Thanks in advance. See code samples below.

DownloadBusinessEntityAsync 是我们的应用程序调用的方法:

DownloadBusinessEntityAsync is the method our application calls:

    #region DownloadBusinessEntity
    public async Task<BusinessEntity> DownloadBusinessEntityAsync(string businessEnityId)
    {
        BusinessEntity ret = new BusinessEntity();

        var client = new DownloadContext();

        try
        {
            Func<AsyncCallback, object, IAsyncResult> begin = (callback, state) => client.BeginDownloadBusinessEntity(businessEnityId, callback, state);
            Func<IAsyncResult, BusinessEntity> end = client.EndDownloadBusinessEntity;

            // ***THIS TAKES FIVE MINUTES TO FINISH***
            ret = await Task<BusinessEntity>.Factory.FromAsync(begin, end, null);

            if (client.State != CommunicationState.Faulted)
                client.Close();
            else
                client.Abort();
        }
        catch (Exception ex)
        {
            client.Abort();
        }

        return ret;
    }
    #endregion

DownloadContext 是WCF客户端:

public partial class DownloadContext : ClientBase<IDownloadService>, IDownloadService, IDownloadContext, IDisposable
{
    public BusinessEntity DownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes)
    {
        return base.Channel.DownloadBusinessEntity(agencyId, activeHashCodes);
    }

    public IAsyncResult BeginDownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes, AsyncCallback callback, object asyncState)
    {
        return base.Channel.BeginDownloadBusinessEntity(agencyId, activeHashCodes, callback, asyncState);
    }

    public BusinessEntity EndDownloadBusinessEntity(IAsyncResult result)
    {
        return base.Channel.EndDownloadBusinessEntity(result);
    }
}

IDownloadService 是WCF客户端实现的合同.

IDownloadService is the contract the WCF client implements.

[ServiceContract(Namespace = "http://namespace.com/services/v1")]
public partial interface IDownloadService
{
    [OperationContract(ProtectionLevel=ProtectionLevel.Sign, Action="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntity", ReplyAction="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntityResponse")]
    BusinessEntity DownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes);

    [OperationContract(AsyncPattern=true, ProtectionLevel=ProtectionLevel.Sign, Action="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntity", ReplyAction="http://namespace.com/services/v1/IDownloadService/DownloadBusinessEntityResponse")]
    IAsyncResult BeginDownloadBusinessEntity(string agencyId, IEnumerable<int> activeHashCodes, AsyncCallback callback, object asyncState);

    BusinessEntity EndDownloadBusinessEntity(IAsyncResult result);

}

推荐答案

如果您只是不想阻止UI,则将其移至后台线程.不需要所有WCF异步内容即可实现您的目标.像这样:

If you simply don't want to block the UI then move that work to a background thread. All that async WCF stuff is not needed to achieve your goal. Something like:

await Task.Run(() => DownloadBusinessEntityAsync(...));

如果愿意,您可以同步 DownloadBusinessEntityAsync .

And you can make DownloadBusinessEntityAsync sync if you like.

这篇关于异步WCF服务调用阻止UI线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆