| 加入收藏| 设为首页| 联系我们

首页 站长学习 站长之家 源码下载 建站素材 书籍教程 常用工具
 您现在的位置: 动力中国 >> 网络编程 >> ASP.NET教程 >> 文章正文  
 [组图]WCF:双向通讯,枷锁机制,线程并发的一些简单理解(二)
 

WCF:双向通讯,枷锁机制,线程并发的一些简单理解(二)

http://www.domcn.org  文章来源:本站收藏  点击数:

  关键字:WCF:双向通讯,枷锁机制,线程并发的一些简单理解(二)

这一部分我将简单的介绍我门的具体代码实现,因为代码中已经做了许多解释,所以不再浪费口舌,我简单的粘贴如下,我想阐述以下关于线程并发的一些问题. 

服务契约的定义:

namespace JeffBarnes.WCF.Samples.CallbackDemo.Service
{
    // NOTE: The use of one way service operations allows the callback to occur while
    //       still using the single concurrency mode rather than Reentrant or Multiple.

    /**//// <summary>
    /// Beer Inventory Service Operations
    /// </summary>
    [ServiceContract(
        Name = BeerInventoryService,
        Namespace = http://jeffbarnes.net/wcf/samples/client_callback/BeerInventoryService/,
        SessionMode = SessionMode.Required,
        CallbackContract = typeof(IBeerInventoryCallback))]
    public interface IBeerInventory
    {
        /**//// <summary>
        /// Guest arrived at the party for the sole purpose of drinking beer
        /// </summary>
        /// <param name=name>Name of the guest</param>
        /// <return>Number of available beers</return>
        [OperationContract()]
        int JoinTheParty(string guestName);

        /**//// <summary>
        /// Someone graciously brought beer to the party
        /// </summary>
        /// <param name=numberOfBeers>Number of beers brought</param>
        [OperationContract(IsOneWay = true)]
        void MakeBeerRun(string guestName, int numberOfBeers);

        /**//// <summary>
        /// Someone drank a beer
        /// </summary>
        [OperationContract(IsOneWay = true)]
        void DrinkBeer(string guestName);

        /**//// <summary>
        /// You dont have to go home, but you cant stay here
        /// </summary>
        [OperationContract(IsOneWay = true)]
        void LeaveTheParty(string guestName);
    }
}

回调契约的定义:

namespace JeffBarnes.WCF.Samples.CallbackDemo.Service
{
    // NOTE: The use of one way service operations allows the callback to occur while
    //       still using the single concurrency mode rather than Reentrant or Multiple.

    /**//// <summary>
    /// Beer Inventory Callback Service Operations
    /// </summary>
    /// <remarks>
    /// The ServiceContract attribute is not explicitly required for the callback interface.
    /// 
    /// By specifying IBeerInventoryCallback as the CallbackContract in IBeerInventory, 
    /// an implicit ServiceContract attribute is applied to this interface.
    /// </remarks>
    public interface IBeerInventoryCallback
    {
        /**//// <summary>
        /// Notifies the client that a guest has joined the party
        /// </summary>
        /// <param name=guestName>Name of the guest</param>
        [OperationContract(IsOneWay = true)]
        void NotifyGuestJoinedParty(string guestName);

        /**//// <summary>
        /// Notifies the client that beer inventory has changed
        /// </summary>
        /// <param name=guestName>Name of the guest</param>
        /// <param name=numberOfBeers>Number of beers that were drank or brought</param>
        [OperationContract(IsOneWay = true)]
        void NotifyBeerInventoryChanged(string guestName, int numberOfBeers);

        /**//// <summary>
        /// Notifies the client that a guest has left the party
        /// </summary>
        /// <param name=guestName>Name of the guest</param>
        [OperationContract(IsOneWay = true)]
        void NotifyGuestLeftParty(string guestName);
    }
}

  我门为了更好的呈现我门的服务,我门或许设计一个客户端的窗体。譬如我门也许设计如下的窗体。然后,我门希望,通过我门的窗体界面来调用我门的服务。

 

现在,当用户操作窗体的时候,相应的操作调用远程服务,对订阅者来说,一些操作将导致回调操作。然而,在windows窗体程序和WPF程序下进行具有回调操作的远程服务的调用将会引起一个问题。为什么我以前没碰到过这中情况呢,那是因为或许你的客户端程序是Console程序。如果窗体线程调用一个服务操作(具有回调操作的服务),将会引起死琐。

假设我门的编码有这么一句话。
this.BeerInventory=_proxy.JoinTheParty(this.txtGuestName.Text);
this是窗体,BeerInventory是窗体属性。乍一看,好象没有问题。但是考虑一下什么将会发生。当服务操作从窗体线程被调用,它将锁住直到返回值返回。然而,在发送回返回值以前,服务操作会调用一个发生在客户端的回调操作,而回调操作是被Marshal在窗体线程下。因为窗体线程为了返回值仍然在苦苦等待,死锁将会发生,其实问题的根源与同步上下文有关。同步上下文也是一中上下文,这我上文已经进行了阐述。我门说过回调操作,让服务端线程和客户端线程确立了联姻关系。客户端的回调操作将在一个特殊的客户端线程中执行。我门在设计客户端的时候,通常要设计友好的窗体界面,然后操作窗体控件,请注意,操作系统为了保证这些窗体或者对窗体控件的操作不被任何外界破坏,当然需要一个相关的线程来提供这中保障。但是,如果我门把回调操作放在这个窗体线程中,就回发生一个有意思的问题,与服务端建立联姻关系的回调线程和窗体线程是同一个线程。尽管在一个线程下回调操作可以操作窗体属性,但是回引发死锁。

让客户端的回调操作脱离同步上下文是一中简单尝试。幸运的是,WCF提供了一个简单的机制来让客户端的操作脱离同步上下文,通过覆盖同步上下文的自动的联姻。同步上下文的这中行为能够被关闭,通过设置CallbackBehavior的属性UseSynchronizationContext为false.如果做此,WCF将不在保证提供一个特别的线程来保证客户端的回调操作与服务端具有联姻关系。相反,回调操作将被执行在一个工作线程中。
[CallbackBehavior(UseSynchronizationContext = false)]


这样的话,执行回调操作的线程就与窗体操作的线程不是一个线程。但是又引起一个新的问题。既然不是一个线程,那么回调操作怎么能操作窗体的属性或者方法或者控件呢?确实不能。

在回调操作的线程中我门可以执行一个特别的委托,而这中委托恰恰提供了这么一种机制,通过它的纽带作用使的具有回调操作的线程能够与窗体线程通讯的能力。
SendOrPostCallback callback =
    delegate (object state)
    { this.WritePartyLogMessage(String.Format({0} has joined the party.,
    state.ToString())); };

_uiSyncContext.Post(callback, guestName);
至此。我门的问题已经全部解决。
我这里只是做个大概介绍,更多解释和代码实现请阅读源代码。


WCF:双向通讯,枷锁机制,线程并发的一些简单理解(二)
  • 上一篇文章:

  • 下一篇文章:
  •  热门文章
    普通文章 电子邮件改头换面 四公司畅谈未
    普通文章 PC病毒史上最声名狼藉的八大病
    普通文章 Rails系统中的AJAX开发技术简析
    普通文章 基于ASP.NET AJAX框架实现表单
    普通文章 开发ASP.NET AJAX客户端定制行
    普通文章 用JFreeChart对JSP报表进行增强
    普通文章 SQL Server 2005上的CLR和ADO.
    普通文章 SQL Server 2005的XML支持机制
    普通文章 Firefox中标签式浏览技巧大全
    普通文章 Tomcat中的Session和Cookie大揭
     
     推荐文章
    推荐文章 把Google地图嵌入网页 就是这么
    推荐文章 迅雷搜索候选资源出错的解决
    推荐文章 轻松去除迅雷里的各种广告和资
    推荐文章 突破限制 免费领养到QQ空间五级
    推荐文章 Rational统一过程RUP贴近中小软
    推荐文章 构建自己的轻量级XML DOM分析程
    推荐文章 WPS Office 2007技巧:妙用配置
    推荐文章 Excel 2007:求余数函数实用进阶
    推荐文章 浅谈ASP.NET的Postback
    推荐文章 软件开发中项目需求管理简述
     
     相关文章
    没有相关文章
    设为首页 | 加入收藏 | 广告合作 | 联系站长 | 版权申明 |
    动力中国为网友提供免费学习资料,可用资源,如果您认为我们的相关内容侵害到了您的权利请联系管理员
    Copyright © 2006-2008 domcn.org All Rights Reserved.