首页 新闻 会员 周边

WCF服务,寄宿在Winform窗体中,项目中的性能问题,急需人才给点点子

0
悬赏园豆:100 [已解决问题] 解决于 2012-07-30 10:03

这个问题很紧急,希望知道的朋友能够告诉我,或者来视频或语音交流也在所不惜,因为我这方面的经验实在是太缺乏了...

说下项目的具体环境:

1. Andirons前端点菜,基于IPad的点菜系统

2. WCF后台服务(很简单的WCF服务,就使用了一下ServiceHost开启下服务,发布一下定义的接口)

 

说下我的问题:

1. 10台IPad同时提交菜单,会出现卡死的现象(这个卡死就是反应时间太长,隔个半天才有反应)

(当时我的猜测是后台窗体是单线程操作,会出现排队等待的现象,是否应该使用异步(多线程)来做)

这种问题是否是并发问题,该怎么解决呢?

 

2. 如果WCF服务开的时间长了,那么Andirons端在调用的时候会出现延迟的情况

(为什么服务的开的时间越久,Andirons端调用的反应也会越来越慢)

Service重启之后,速度就会非常的快,这到底是什么原因呢?

 

3. 对于第一个问题,如果每个跟数据库交互的方法都要用异步来做,编程困难会不会很大

 

下面是我的AppConfig文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="LoggingManager" type="Transight.Common.Logging.LoggingManagerSection,Transight.Common.Logging"/>
    <section name="DBAccessBroker" type="Transight.Common.DBAccessBroker.DBAccessBrokerSection,Transight.Common.DBAccessBroker"/>
    <section name="MessageBusService" type="Transight.Common.MessageBus.Transports.TransportSettings,Transight.Common.MessageBus.Transports"/>
  </configSections>
  <system.serviceModel>
    <services>
      <service name="Transight.POS.FrontendService.JsonService.Operations" behaviorConfiguration="FrontendService">
        <endpoint
          address="" binding="basicHttpBinding"  bindingConfiguration="httpBinding_Config"
          contract="Transight.POS.FrontendService.Contracts.IJsonOperation" >
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/FrontendWebService/"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="FrontendService">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="httpBinding_Config" maxReceivedMessageSize="2147483647"   maxBufferSize="2147483647" messageEncoding="Text"
          sendTimeout="00:10:00">
          <security mode="None"></security>
          <readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647"/>
        </binding>
      </basicHttpBinding>
    </bindings>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="false" />
  </system.serviceModel>
  <LoggingManager>
    <Loggings>
      <add LoggingName="Default" LoggingEntity="FileLogging" LogFilePath="c:\Log" LogSeparateByLevel="true" LogFileName="Transight.POSV4.Logs"/>
      <!--<add LoggingName="PluginRuntime" LoggingEntity="FileLogging" LogFilePath="c:\Log" LogSeparateByLevel="true" LogFileNamee="Transight.POSV4.Logs" LogSource="PluginRuntime"/>
      <add LogSource="PrintingMgr" LoggingName="PrintingMgrLog" LoggingEntity="FileLogging" LogFilePath="c:\Log" LogSeparateByLevel="true" LogFileName="Transight.POSV4.Logs"/>
      <add LogSource="PrintingJob" LoggingName="PrintingJobLog" LoggingEntity="FileLogging" LogFilePath="c:\Log" LogSeparateByLevel="true" LogFileName="Transight.POSV4.Logs"/>-->
    </Loggings>
  </LoggingManager>
  <DBAccessBroker>
    <DBAccess FullName="Transight.Common.DBAccess.SQLDBAccess" Namespace ="Transight.Common.DBAccess"/>
    <DBConnections>
      <add ConfigFile="C:\CommonConfig.xml" ConnStringNode="ConnStr" IsConnStrEncrypted="false" SystemName="Tablet" IsServer="false"/>
    </DBConnections>
  </DBAccessBroker>
  <MessageBusService ServiceAddress="net.tcp://192.168.23.50:8787/MessageBusService" />
</configuration>
TimYang的主页 TimYang | 初学一级 | 园豆:12
提问于:2012-07-24 16:45
< >
分享
最佳答案
0

1,windows 2003/2008之类的server会默认开启优化后台服务,所以你的Winform应用程序优先级不高;

2,自宿主的 wcf 应用需要开启gc server模式;

3,启动 ServiceHost 的操作放置在非UI线程中;

收获园豆:50
Launcher | 高人七级 |园豆:45045 | 2012-07-24 17:03

第二个和第三个回答费解,能否有文章参考...

TimYang | 园豆:12 (初学一级) | 2012-07-24 17:10

@程序猿就是我: 在你的配置文件中:<runtime><gcServer enable="true"></gcServer> </runtime>

Launcher | 园豆:45045 (高人七级) | 2012-07-24 17:25

@程序猿.码农: 说实话,我实在不明白你所谓的卡死是啥意思,所以我猜测是你的宿主程序UI失去了响应,因此我建议你new Thread ,然后在线程回掉中启动服务,这只能加速UI响应。数据库异步也简单,自己封装个AsyncResult就行,SqlCommand也提供了BeginExecute方法。

Launcher | 园豆:45045 (高人七级) | 2012-07-24 17:29

@程序猿.码农: 是的,我发现寄宿WCF服务的窗体都发白了,如,出现了无反应的情况!

TimYang | 园豆:12 (初学一级) | 2012-07-24 17:34

@程序猿就是我: 你可以先通过在新线程中宿主服务来改善你的UI响应。

Launcher | 园豆:45045 (高人七级) | 2012-07-24 17:53

@程序猿.码农: 那么代码是不是这样写:

ThreadPool.QueueUserWorkItem(StartService);

下面是启动WCF服务的方法

private void StartService(object obj)
{
ServiceHost host = new ServiceHost(typeof(JsonService.Operations));
host.Open();
}

这样的写法可以吗?还是我要使用Thread才行!

TimYang | 园豆:12 (初学一级) | 2012-07-24 18:23

@程序猿就是我: 这样不行,host出了作用域就释放了。你的 host.Open()后,将当前线程阻塞住。

private void StartService(object obj)

{

 ServiceHost host = ....

host.Open();

WaitForSingleObject(event); // 这是伪码,阻塞当前线程,等待信号。

host.Close();
}

当然,这样并不能完全的解决问题,你还需要检查你的 service 里哪些方法占用了UI线程。

Launcher | 园豆:45045 (高人七级) | 2012-07-25 09:15

@程序猿.码农: 

WaitForSingleObject(event); 

这句代码的意思是我另写一个方法,阻止当前线程!

可是我的当前线程还需要做其它一些工作!这样两者会冲突吗?

TimYang | 园豆:12 (初学一级) | 2012-07-25 09:44

@程序猿就是我: 在C#,可以使用 ManualResetEvent,ManualResetEvent.WaitOne 来等待有其它线程触发 Event。你当前线程除了host.Open(),还要做啥?是必须紧跟host.Open()后串行执行的吗?

Launcher | 园豆:45045 (高人七级) | 2012-07-25 09:50

@程序猿.码农: 

Open()方法后面不执行东西,就是我的WCF服务开起来之后,会有很多客户端连过来,后台有个时钟会一直跑,刷新有哪些客户端连过来了,然后把客户端的基本数据显示在窗体上...

就这么多了!

TimYang | 园豆:12 (初学一级) | 2012-07-25 10:01

@程序猿就是我: 你如何实现你的显示客户端连接信息的?Timer的频率是多少?

Launcher | 园豆:45045 (高人七级) | 2012-07-25 10:04

@程序猿.码农: 客户端会传一个ClientName参数过来,先验证是否有效,如果正确就去数据库获取相应的客户端信息,然后放到一个字典类中,最后显示在窗体上面!

时钟频率是5秒!

不知道我的描述是否可以啊!

TimYang | 园豆:12 (初学一级) | 2012-07-25 10:11

@程序猿就是我: 说实话,不太明白,你把重要的信息都遗漏了。客户端每次调用都传递一个ClientName参数吗?客户端每次调用都会触发服务器同步查询数据库吗?Timer每5秒直接从字典读数据显示到UI吗?

Launcher | 园豆:45045 (高人七级) | 2012-07-25 10:17

@程序猿.码农: 

不好意思我说的不够清楚,服务端有很多方法,每个方法都有一个clientname参数,只有第一次连接时候才去数据库获取这个clientname相关的信息,显示到窗体上,当连接成功后客户端点菜的信息也会显示到窗体上面!时钟就是每五秒从字典读数据!

顺便问一下<runtime><gcServer enable="true"></gcServer> </runtime>

这个节点我找不到,是随便写的吗?

TimYang | 园豆:12 (初学一级) | 2012-07-25 10:31

@程序猿就是我: http://msdn.microsoft.com/zh-cn/library/0kk0kk35

你是通过字典里是否有clientName来判断是否为第一连接的吗?

另外,你new的Thread,设置为Background,线程单元模型设置为 MTA。

Launcher | 园豆:45045 (高人七级) | 2012-07-25 10:38
其他回答(5)
0

对。可以 放在console中。

收获园豆:10
無限遐想 | 园豆:3740 (老鸟四级) | 2012-07-24 17:05

这个好像不现实了,项目已经做的快好了,现在该宿主会很麻烦的!

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-24 17:25

@程序猿就是我: 是不是 宿主 有何 ui 进行交互的地方呢?按理说 开几个 是没有问题的哦。本来 就是多线程哦。除非 有共享资源哦。

支持(0) 反对(0) 無限遐想 | 园豆:3740 (老鸟四级) | 2012-07-24 17:37

@無限遐想: 宿主 改 一下。怎么会麻烦呢?你直接在program理,直接启动就好了。不要调用窗体。加一个console.readline()

支持(0) 反对(0) 無限遐想 | 园豆:3740 (老鸟四级) | 2012-07-24 17:40

@無限遐想: 哪有这么容易就能改变啦,因为这个窗体里面还有一些操作!

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-24 18:24
0

1,把配置拿出来看看,并发10个不算什么。

2,说明程序写的有问题,有资源没释放或者内存泄露的情况,很有可能数据库连接用完没释放。

3,推测点菜什么的数据量不大,逻辑也不耗时,没必要异步。

4,如上,另外用个非UI线程用来跑host

收获园豆:10
arg | 园豆:1047 (小虾三级) | 2012-07-24 17:11

你想看AppConfig文件吗?

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-24 17:17

配置文件已经贴上去了,求指教!

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-24 17:24

@程序猿就是我: 

没看到特殊的关于并发的配置,默认并发最大为10,看看artch的神作http://www.cnblogs.com/artech/archive/2010/03/19/1690118.html,关于并发的,应该可以找到解决方法。我觉得程序可能写的有问题,我写的专门计算数据的,上来内存就几百兆,没日没夜的跑都没事。

把servicehost放非UI线程很重要

支持(0) 反对(0) arg | 园豆:1047 (小虾三级) | 2012-07-24 17:32

@arg: 谢谢你啊,我会认真看文章的,有问题我再联系你啊!

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-24 17:35
0

寄宿在IIS吧,自寄宿的EXE,默认都是单线程处理的。。。。。。。。。。。。

所以越来越慢。。。。。。。。。

收获园豆:10
伦惠峰 | 园豆:217 (菜鸟二级) | 2012-07-25 14:07

那现在只能寄宿在窗体中了,有什么好的优化方案吗?对于越来越慢的问题,有没有好的方案...

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-25 14:30

大哥,有没有什么好点子告诉我,一直没有接触过服务编程啊,求解!

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-25 15:52
0

应用[ServiceBehavior(UseSynchronizationContext = false)]

收获园豆:20
Artech | 园豆:287 (菜鸟二级) | 2012-07-26 08:16

这个特性是放在我发布的接口上面还是实现接口的类上面?老A

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-26 08:52

@程序猿就是我: Service类型

支持(0) 反对(0) Artech | 园豆:287 (菜鸟二级) | 2012-07-26 08:58

@Artech: 老A,除了上面的建议之外,对于我写出来的问题,你还有什么建议指点给我呀?谢谢了!

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-26 09:46
0

你选择winform,肯定是有业务需要的。业务流程是不是这样的,前端选择菜,通过wcf传输给后端,后端通过winform显示客户点的菜,然后后厨看看有没有原材料了,也就是能否接受这个点菜,接受与否都会操作一下,然后你的前端会看到效果,决定继续点菜还是告诉客人换菜,后厨做好菜了,就通过winform操作一下,前端收到菜已做好的信号,就去拿菜给客人,业务流程是不是这样的呢?整个过程需要后端winform和前端的交互。所以你选择winform作为host。

Virus-BeautyCode | 园豆:1619 (小虾三级) | 2012-07-31 09:19

对的,其实你说的业务流比较复杂了,我们后台紧紧查看那每个ipad的状态,以及点了多少菜!

我想请教下,怎么通过代码解决一下并发的问题呀!

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-31 16:25

@程序猿就是我: 其实你说的那些操作我们还有一个POS机系统来进行控制!

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-31 16:26

@程序猿就是我: 现在我的做法是:

1.把服务单独放到一个线程里面

Thread thread = new Thread(StartService) { IsBackground = true };
thread.SetApartmentState(ApartmentState.MTA);
thread.Start();

2.然后设置并发模式以及实例模式

[ServiceBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]

3.在配置文件里面增加并发量连接数

<serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000"/>

不知道这些配置能不能够满足这些配置。。。

支持(0) 反对(0) TimYang | 园豆:12 (初学一级) | 2012-07-31 16:31
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册