WCF宿主WINFORM多客户端操作变慢

时间:2022-09-12 20:20:23
使用WINFORM作为WCF宿主,使用两个客户端同时查询表的时候查询速度会变慢,WINFORM宿主界面会无响应,查找不到问题原因,请教各位大神们帮忙
附上设计代码:

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>

  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="MyTcpBinding" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="2147483647" maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>

    <services>
      <service behaviorConfiguration="MyBehavior" name="VCFService.Service1">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:8081//"/>
          </baseAddresses>
        </host>
        <endpoint address="S1" binding="netTcpBinding" bindingConfiguration="MyTcpBinding" contract="VCFService.IService1"></endpoint>
        <endpoint address="mex111" binding="netTcpBinding" contract="IMetadataExchange" bindingConfiguration="MyTcpBinding" ></endpoint>

      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyBehavior">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="false"/>
          <serviceDebug includeExceptionDetailInFaults="true" />
          <dataContractSerializer maxItemsInObjectGraph="6553600"/>
        </behavior>
        <behavior name="ThrottledBehavior">
          <serviceThrottling maxConcurrentCalls="5000" maxConcurrentSessions="5000" maxConcurrentInstances="5000" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <directoryBrowse enabled="true" />
  </system.webServer>

  <runtime>
    <gcServer enabled="true" />
  </runtime>

  <appSettings>
    <add key="server" value="127.0.0.1" />
    <add key="DataBaseName" value="dsportmis" />
    <add key="DBUserId" value="sa" />
    <add key="DBPassWord" value="12345" />
  </appSettings>

</configuration>


服务端源码:

const int SleepTime = 100;
        public ServiceHost _serviceHost = null;
        private Thread _thread;
        private bool _isRunning;
        public ThreadServiceHost(Type serviceType)
        {
            
            try
            {
                _serviceHost = new ServiceHost(serviceType);
                _thread = new Thread(RunService);
                _thread.Start();
            }
            catch (System.Exception ex)
            {
                ShwMsgForView.ShwMsgforView(Comm.memoEdit, "启动服务失败......." + ex.ToString());

            } 

            
        }
        void RunService()
        {
            try
            {               
                _serviceHost.Open();
                _isRunning = true;
                VCFService.ShwMsgForView.ShwMsgforView(Comm.memoEdit, "服务启动完成.......");
                //while (_isRunning)
                //{
                //    Thread.Sleep(SleepTime);
                //}
                //_serviceHost.Close();
                //((IDisposable)_serviceHost).Dispose();
            }
            catch (Exception ex)
            {
                if (_serviceHost != null)
                    _serviceHost.Abort();
                ShwMsgForView.ShwMsgforView(Comm.memoEdit, "启动服务失败......." + ex.ToString());
                //throw ex;
            }
        }
  [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any, UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
    public class Service1 : IService1,IDisposable
    {
public string GetXml(CurUser user, string DtSql)
        {
            Thread.Sleep(100);
            Func<CurUser,string, string> method = GetXml1;
            IAsyncResult cookie = method.BeginInvoke(user, DtSql, null, null);
            ShwMsgForView.ShwMsgforView(Comm.memoEdit, DtSql);
            string result = method.EndInvoke(cookie);
            
            return result;
           
        }
        public string GetXml1(CurUser user, string DtSql)
        {
            using (DbHelper dbhelper = new DbHelper())
            {
                Thread.Sleep(100);
                return dbhelper.GetXml(user, DtSql);
            }
        }

public string GetXml(CurUser user, string DtSql)
        {
            try
            {
                DataSet dtResult;
                string strResult;
                StringBuilder strSql = new StringBuilder();
                strSql.Append(DtSql);
                dtResult = GetDataSetByProc(user, CommandType.Text, strSql.ToString());
                
                return strResult=XmlUtil.Serializer(typeof(DataTable), dtResult.Tables[0]);

            }
            catch (System.Exception ex)
            {
                Comm.OuntPutLog("检索数据'" + DtSql + "'发生错误:" + ex.ToString());
                throw new FaultException(ex.ToString());

            }
        }

public DataSet GetDataSetByProc(CurUser user, CommandType type, string procName, params SqlParameter[] parameters)//在用,查询表
        {
            if (user == null)
            {
                user = new CurUser();
            }
            ShwMsgForView.ShwMsgforView(Comm.memoEdit, user.UserName + "(" + user.IPAddress + ")" + "用户执行:" + procName);
            using (SqlConnection conn = new SqlConnection(connString))
            {
                conn.Open();
                using (SqlCommand cmd = new SqlCommand())
                {
                    cmd.Connection = conn;
                    cmd.CommandText = procName;
                    cmd.CommandType = type;
                    cmd.CommandTimeout = timeout;
                    cmd.Parameters.AddRange(parameters);
                    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                    {
                        using (DataSet ds = new DataSet())
                        {
                            try 
                            { 
                                da.Fill(ds);
                                conn.Close();
                                return ds;
                            }
                            catch (System.Exception ex)
                            {
                                throw new FaultException(ex.ToString());                          
                            }
                        }
                    }
                }
            }
        }

public class ShwMsgForView
    {
        delegate void ShwMsgforViewCallBack(DevExpress.XtraEditors.MemoEdit memoEdit1, string text);
        public static void ShwMsgforView(DevExpress.XtraEditors.MemoEdit memoEdit1, string text)
        {
            Comm.OuntPutLog(text);
            if (memoEdit1==null)
            {
                return;
            }
            if (memoEdit1.InvokeRequired)
            {
                ShwMsgforViewCallBack shwMsgforViewCallBack = ShwMsgforView;
                memoEdit1.Invoke(shwMsgforViewCallBack, new object[] { memoEdit1, text });
            }
            else
            {
                string Strlog = "\r\n===========" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "===========\r\n" + text + "\r\n";          
                memoEdit1.Text = Strlog + memoEdit1.Text;
                if (memoEdit1.Lines.Length>=5000)
                {
                    memoEdit1.Text = "";
                }
            }

        }
    }

public static void OuntPutLog(string text, Boolean IsOpen = false)//操作日志,最新日志放在最前面
        {
            try
            {
                string Strlog = "\r\n===========" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "===========\r\n" + text + "\r\n";
                string strFilePath = sPath + "\\Log\\OptLog" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
                File.AppendAllText(strFilePath, "", System.Text.Encoding.Default);
                string strOldText = File.ReadAllText(strFilePath, System.Text.Encoding.Default);
                File.WriteAllText(strFilePath, Strlog, System.Text.Encoding.Default);
                File.AppendAllText(strFilePath, strOldText, System.Text.Encoding.Default);
                if (IsOpen)
                {
                    try
                    {
                        Process p = new Process();
                        p.StartInfo.FileName = strFilePath;
                        p.Start();
                    }
                    catch (System.Exception ex)
                    {
                        throw new FaultException(ex.ToString());
                    }
                }
            }
            catch (System.Exception ex)
            {
                //ErrorLogWrite("写操作日志错误:" + ex.ToString());
            }

        }

12 个解决方案

#1


为什么选择winform 作为wcf的宿主呢?

#2


单看你的 GetXml 方法吧:

1. 写 Sleep 是动了什么歪脑筋?故意阻塞当前程序是要干什么?一个人请求阻塞100毫秒,10个请求就阻塞1秒?

2. Func<.....> 那个是委托,那个不叫 method,method是method、委托是委托,二者是不同的概念。这就好像一个是“祖国”,另一个是“海外殖民地”,是两回事。你可以起一个雷人的名字(就好像设计模式那样),但是不要为变量起一个张冠李戴容易引起误会的名字。

3. 你的多线程编程完全是无意义的。你用了多线程异步的语法,来模拟一个同步操作流程。你在执行了 BeginInvoke 之后,接下来的代码操作就阻塞在那里等待 EndInvoke 的完成,这种东西可能只在 msdn 上给你讲解、演示最低级的编程语法时才有的(幼儿园的编程方式)。真正的多线程编程设计是“回调”式的,在 BeginInvoke 之后绝对不会去阻塞地等待什么 EndInvoke,而是直接就结束了 GetXml 方法了!EndInvoke方法应该放到 BeginInvoke 所注册的回调方法中的第一句去执行,然后这个GetXml再调用客户程序所要的回调方法。

也就是说,一个异步回调的 GetXml 方法从接口定义上就会是这样
public void GetXml(CurUser user, string DtSql, Action<string> callback)
{
    .......
}
这样一个异步回调格式的方法,才可以承载其多线程并发操作之实际内涵。


在.net4.5以上版本,发明了一种 async/await 语法,这用来迎合那些满脑子只有同步方法语法的人。但是这显然是逻辑上比较复杂的,对使用者的要求比使用回调方式更高。否则,假设真的是一个只知道同步调用的人来使用这个新语法,那么这个语法就成了笑柄了,因为一个人没有实现非常充分地理解异步回调设计,又怎么会理解 asyn/await 语法?所以那些说“这个语法可以使程序员使用同步调用语法来编写异步多线程程序”其实是个败笔、是个谎言。程序员一旦编写代码、一旦调试,就知道不理解自己的代码了。

没有设计异步回调代码的习惯,怎么可能知道什么叫做多线程并发?

#3


随便一个 javascript 程序员都知道异步回调的机制。例如使用 jQuery 中的 jQuery.ajax 函数等等。因此他们的“感觉上”就学会了编写异步回调的程序。而异步回调程序,就为其后台承载多线程并发执行流程提供了基本的保证。

所以由此可见,许多.net 编程者在这个方面的平均入门知识水平是不如学过一点 jQuery 的编程者的知识水平的。对于异步编程、多线程并发程序设计,缺乏基础知识。

在 javascript 最新版本中也引入了 async/await 语法,可能再过2年就会在许多 js 开源插件中看到这种语法。但是 jQuery 等等已经流行了很多年,程序员都习惯写异步回调的代码,而且甚至都“写腻了”。

可是大多数 .net 程序员并没有写腻,而是还没有基本概念。

#4


引用 3楼以专业开发人员为伍 的回复:
随便一个 javascript 程序员都知道异步回调的机制。例如使用 jQuery 中的 jQuery.ajax 函数等等。因此他们的“感觉上”就学会了编写异步回调的程序。而异步回调程序,就为其后台承载多线程并发执行流程提供了基本的保证。

所以由此可见,许多.net 编程者在这个方面的平均入门知识水平是不如学过一点 jQuery 的编程者的知识水平的。对于异步编程、多线程并发程序设计,缺乏基础知识。

在 javascript 最新版本中也引入了 async/await 语法,可能再过2年就会在许多 js 开源插件中看到这种语法。但是 jQuery 等等已经流行了很多年,程序员都习惯写异步回调的代码,而且甚至都“写腻了”。

可是大多数 .net 程序员并没有写腻,而是还没有基本概念。
看您给所有人的回复,都只批评哪里写的有问题,我自学的c#,看您这种专家的批评我依然不懂得改,请您在批评的同时告诉我应该怎么写才是对的

#5


引用 1楼衣舞晨风 的回复:
为什么选择winform 作为wcf的宿主呢?
使用iis的时候我单客户端重复执行查询40次后会提示应答超时,唉(๑◕︵◕๑)

#6


引用 2 楼 sp1234 的回复:
单看你的 GetXml 方法吧:

1. 写 Sleep 是动了什么歪脑筋?故意阻塞当前程序是要干什么?一个人请求阻塞100毫秒,10个请求就阻塞1秒?

2. Func<.....> 那个是委托,那个不叫 method,method是method、委托是委托,二者是不同的概念。这就好像一个是“祖国”,另一个是“海外殖民地”,是两回事。你可以起一个雷人的名字(就好像设计模式那样),但是不要为变量起一个张冠李戴容易引起误会的名字。

3. 你的多线程编程完全是无意义的。你用了多线程异步的语法,来模拟一个同步操作流程。你在执行了 BeginInvoke 之后,接下来的代码操作就阻塞在那里等待 EndInvoke 的完成,这种东西可能只在 msdn 上给你讲解、演示最低级的编程语法时才有的(幼儿园的编程方式)。真正的多线程编程设计是“回调”式的,在 BeginInvoke 之后绝对不会去阻塞地等待什么 EndInvoke,而是直接就结束了 GetXml 方法了!EndInvoke方法应该放到 BeginInvoke 所注册的回调方法中的第一句去执行,然后这个GetXml再调用客户程序所要的回调方法。

也就是说,一个异步回调的 GetXml 方法从接口定义上就会是这样
public void GetXml(CurUser user, string DtSql, Action<string> callback)
{
    .......
}
这样一个异步回调格式的方法,才可以承载其多线程并发操作之实际内涵。


在.net4.5以上版本,发明了一种 async/await 语法,这用来迎合那些满脑子只有同步方法语法的人。但是这显然是逻辑上比较复杂的,对使用者的要求比使用回调方式更高。否则,假设真的是一个只知道同步调用的人来使用这个新语法,那么这个语法就成了笑柄了,因为一个人没有实现非常充分地理解异步回调设计,又怎么会理解 asyn/await 语法?所以那些说“这个语法可以使程序员使用同步调用语法来编写异步多线程程序”其实是个败笔、是个谎言。程序员一旦编写代码、一旦调试,就知道不理解自己的代码了。

没有设计异步回调代码的习惯,怎么可能知道什么叫做多线程并发?

p哥建议不建议用async/await呢?我是把它当做架构(c端的web架构)的基础设施在用

#7


引用 4 楼 u013703837 的回复:
Quote: 引用 3楼以专业开发人员为伍 的回复:
随便一个 javascript 程序员都知道异步回调的机制。例如使用 jQuery 中的 jQuery.ajax 函数等等。因此他们的“感觉上”就学会了编写异步回调的程序。而异步回调程序,就为其后台承载多线程并发执行流程提供了基本的保证。

所以由此可见,许多.net 编程者在这个方面的平均入门知识水平是不如学过一点 jQuery 的编程者的知识水平的。对于异步编程、多线程并发程序设计,缺乏基础知识。

在 javascript 最新版本中也引入了 async/await 语法,可能再过2年就会在许多 js 开源插件中看到这种语法。但是 jQuery 等等已经流行了很多年,程序员都习惯写异步回调的代码,而且甚至都“写腻了”。

可是大多数 .net 程序员并没有写腻,而是还没有基本概念。
看您给所有人的回复,都只批评哪里写的有问题,我自学的c#,看您这种专家的批评我依然不懂得改,请您在批评的同时告诉我应该怎么写才是对的

很多时候要讲明一个概念,比如这种线程问题,需要一篇或者几篇文章的篇幅来讲,不是csdn上几句话能讲明白的。
你可以到博客园上看几篇讲线程的文章。p哥的话高度太高,可以指路,细节还得你自己去研究

#8


引用 6 楼 daixf_csdn 的回复:
p哥建议不建议用async/await呢?我是把它当做架构(c端的web架构)的基础设施在用


不要抠这个字眼儿。我是说明“为什么有的人换了好几只越来越贵的笔、结果仍然写不出好文章来”的道理。

这里,先要学会异步回调 设计,没有这个基础就不知道内部机制,那么学 async/await 就更多盲从性了。

#9


正因为是跟自认为已经能堆砌一大堆无关“技术”的人、被技术害惨了的人来说明一个浅显的道理,所以比较费时间。因为他过去2、3年可能都没有学过基础,重新学习基本概念会觉得很不习惯。

#10


这里就是非常适宜的功能点,正好是针对 lz 具体问题来重点说明,我不知道这个“重点说明”跟博客园有什么替代关系。如果有比较针对性的文章,不管是不是博客园上的文章,欢迎贴出链接来。但是当你谈论一个服装设计技术时你不能用一句“大街上批发衣服的地方有很多啊”来说明,当你谈论写一篇畅销小说时不能用一句“网络上垃圾下载站可以下载5G的小说啊”来说明。

这里就是针对当前帖子的重点错误,进行一次重点解决。

#11


有没有人能直接告诉我我错的地方,应该怎么修正 WCF宿主WINFORM多客户端操作变慢

#12


wcf的接口本身就是多线程的。。。楼主你只需要把那些画蛇添足的多线程代码删除掉就好了

#1


为什么选择winform 作为wcf的宿主呢?

#2


单看你的 GetXml 方法吧:

1. 写 Sleep 是动了什么歪脑筋?故意阻塞当前程序是要干什么?一个人请求阻塞100毫秒,10个请求就阻塞1秒?

2. Func<.....> 那个是委托,那个不叫 method,method是method、委托是委托,二者是不同的概念。这就好像一个是“祖国”,另一个是“海外殖民地”,是两回事。你可以起一个雷人的名字(就好像设计模式那样),但是不要为变量起一个张冠李戴容易引起误会的名字。

3. 你的多线程编程完全是无意义的。你用了多线程异步的语法,来模拟一个同步操作流程。你在执行了 BeginInvoke 之后,接下来的代码操作就阻塞在那里等待 EndInvoke 的完成,这种东西可能只在 msdn 上给你讲解、演示最低级的编程语法时才有的(幼儿园的编程方式)。真正的多线程编程设计是“回调”式的,在 BeginInvoke 之后绝对不会去阻塞地等待什么 EndInvoke,而是直接就结束了 GetXml 方法了!EndInvoke方法应该放到 BeginInvoke 所注册的回调方法中的第一句去执行,然后这个GetXml再调用客户程序所要的回调方法。

也就是说,一个异步回调的 GetXml 方法从接口定义上就会是这样
public void GetXml(CurUser user, string DtSql, Action<string> callback)
{
    .......
}
这样一个异步回调格式的方法,才可以承载其多线程并发操作之实际内涵。


在.net4.5以上版本,发明了一种 async/await 语法,这用来迎合那些满脑子只有同步方法语法的人。但是这显然是逻辑上比较复杂的,对使用者的要求比使用回调方式更高。否则,假设真的是一个只知道同步调用的人来使用这个新语法,那么这个语法就成了笑柄了,因为一个人没有实现非常充分地理解异步回调设计,又怎么会理解 asyn/await 语法?所以那些说“这个语法可以使程序员使用同步调用语法来编写异步多线程程序”其实是个败笔、是个谎言。程序员一旦编写代码、一旦调试,就知道不理解自己的代码了。

没有设计异步回调代码的习惯,怎么可能知道什么叫做多线程并发?

#3


随便一个 javascript 程序员都知道异步回调的机制。例如使用 jQuery 中的 jQuery.ajax 函数等等。因此他们的“感觉上”就学会了编写异步回调的程序。而异步回调程序,就为其后台承载多线程并发执行流程提供了基本的保证。

所以由此可见,许多.net 编程者在这个方面的平均入门知识水平是不如学过一点 jQuery 的编程者的知识水平的。对于异步编程、多线程并发程序设计,缺乏基础知识。

在 javascript 最新版本中也引入了 async/await 语法,可能再过2年就会在许多 js 开源插件中看到这种语法。但是 jQuery 等等已经流行了很多年,程序员都习惯写异步回调的代码,而且甚至都“写腻了”。

可是大多数 .net 程序员并没有写腻,而是还没有基本概念。

#4


引用 3楼以专业开发人员为伍 的回复:
随便一个 javascript 程序员都知道异步回调的机制。例如使用 jQuery 中的 jQuery.ajax 函数等等。因此他们的“感觉上”就学会了编写异步回调的程序。而异步回调程序,就为其后台承载多线程并发执行流程提供了基本的保证。

所以由此可见,许多.net 编程者在这个方面的平均入门知识水平是不如学过一点 jQuery 的编程者的知识水平的。对于异步编程、多线程并发程序设计,缺乏基础知识。

在 javascript 最新版本中也引入了 async/await 语法,可能再过2年就会在许多 js 开源插件中看到这种语法。但是 jQuery 等等已经流行了很多年,程序员都习惯写异步回调的代码,而且甚至都“写腻了”。

可是大多数 .net 程序员并没有写腻,而是还没有基本概念。
看您给所有人的回复,都只批评哪里写的有问题,我自学的c#,看您这种专家的批评我依然不懂得改,请您在批评的同时告诉我应该怎么写才是对的

#5


引用 1楼衣舞晨风 的回复:
为什么选择winform 作为wcf的宿主呢?
使用iis的时候我单客户端重复执行查询40次后会提示应答超时,唉(๑◕︵◕๑)

#6


引用 2 楼 sp1234 的回复:
单看你的 GetXml 方法吧:

1. 写 Sleep 是动了什么歪脑筋?故意阻塞当前程序是要干什么?一个人请求阻塞100毫秒,10个请求就阻塞1秒?

2. Func<.....> 那个是委托,那个不叫 method,method是method、委托是委托,二者是不同的概念。这就好像一个是“祖国”,另一个是“海外殖民地”,是两回事。你可以起一个雷人的名字(就好像设计模式那样),但是不要为变量起一个张冠李戴容易引起误会的名字。

3. 你的多线程编程完全是无意义的。你用了多线程异步的语法,来模拟一个同步操作流程。你在执行了 BeginInvoke 之后,接下来的代码操作就阻塞在那里等待 EndInvoke 的完成,这种东西可能只在 msdn 上给你讲解、演示最低级的编程语法时才有的(幼儿园的编程方式)。真正的多线程编程设计是“回调”式的,在 BeginInvoke 之后绝对不会去阻塞地等待什么 EndInvoke,而是直接就结束了 GetXml 方法了!EndInvoke方法应该放到 BeginInvoke 所注册的回调方法中的第一句去执行,然后这个GetXml再调用客户程序所要的回调方法。

也就是说,一个异步回调的 GetXml 方法从接口定义上就会是这样
public void GetXml(CurUser user, string DtSql, Action<string> callback)
{
    .......
}
这样一个异步回调格式的方法,才可以承载其多线程并发操作之实际内涵。


在.net4.5以上版本,发明了一种 async/await 语法,这用来迎合那些满脑子只有同步方法语法的人。但是这显然是逻辑上比较复杂的,对使用者的要求比使用回调方式更高。否则,假设真的是一个只知道同步调用的人来使用这个新语法,那么这个语法就成了笑柄了,因为一个人没有实现非常充分地理解异步回调设计,又怎么会理解 asyn/await 语法?所以那些说“这个语法可以使程序员使用同步调用语法来编写异步多线程程序”其实是个败笔、是个谎言。程序员一旦编写代码、一旦调试,就知道不理解自己的代码了。

没有设计异步回调代码的习惯,怎么可能知道什么叫做多线程并发?

p哥建议不建议用async/await呢?我是把它当做架构(c端的web架构)的基础设施在用

#7


引用 4 楼 u013703837 的回复:
Quote: 引用 3楼以专业开发人员为伍 的回复:
随便一个 javascript 程序员都知道异步回调的机制。例如使用 jQuery 中的 jQuery.ajax 函数等等。因此他们的“感觉上”就学会了编写异步回调的程序。而异步回调程序,就为其后台承载多线程并发执行流程提供了基本的保证。

所以由此可见,许多.net 编程者在这个方面的平均入门知识水平是不如学过一点 jQuery 的编程者的知识水平的。对于异步编程、多线程并发程序设计,缺乏基础知识。

在 javascript 最新版本中也引入了 async/await 语法,可能再过2年就会在许多 js 开源插件中看到这种语法。但是 jQuery 等等已经流行了很多年,程序员都习惯写异步回调的代码,而且甚至都“写腻了”。

可是大多数 .net 程序员并没有写腻,而是还没有基本概念。
看您给所有人的回复,都只批评哪里写的有问题,我自学的c#,看您这种专家的批评我依然不懂得改,请您在批评的同时告诉我应该怎么写才是对的

很多时候要讲明一个概念,比如这种线程问题,需要一篇或者几篇文章的篇幅来讲,不是csdn上几句话能讲明白的。
你可以到博客园上看几篇讲线程的文章。p哥的话高度太高,可以指路,细节还得你自己去研究

#8


引用 6 楼 daixf_csdn 的回复:
p哥建议不建议用async/await呢?我是把它当做架构(c端的web架构)的基础设施在用


不要抠这个字眼儿。我是说明“为什么有的人换了好几只越来越贵的笔、结果仍然写不出好文章来”的道理。

这里,先要学会异步回调 设计,没有这个基础就不知道内部机制,那么学 async/await 就更多盲从性了。

#9


正因为是跟自认为已经能堆砌一大堆无关“技术”的人、被技术害惨了的人来说明一个浅显的道理,所以比较费时间。因为他过去2、3年可能都没有学过基础,重新学习基本概念会觉得很不习惯。

#10


这里就是非常适宜的功能点,正好是针对 lz 具体问题来重点说明,我不知道这个“重点说明”跟博客园有什么替代关系。如果有比较针对性的文章,不管是不是博客园上的文章,欢迎贴出链接来。但是当你谈论一个服装设计技术时你不能用一句“大街上批发衣服的地方有很多啊”来说明,当你谈论写一篇畅销小说时不能用一句“网络上垃圾下载站可以下载5G的小说啊”来说明。

这里就是针对当前帖子的重点错误,进行一次重点解决。

#11


有没有人能直接告诉我我错的地方,应该怎么修正 WCF宿主WINFORM多客户端操作变慢

#12


wcf的接口本身就是多线程的。。。楼主你只需要把那些画蛇添足的多线程代码删除掉就好了