none
方法只有一个线程执行 RRS feed

  • 问题

  • 修改的是别人写的代码,
    C# code
    ?
    1
    2
    3
        public override void ExecuteCommand(PowerSession session, PowerControl.SuperSocketPower.BinaryRequestInfo requestInfo)
            {
                lock (this) {

    我在这个方法里面加了lock。,还是很多线程执行这个方法,啥原因啊?怎么修改?

    please verify my account

    2017年8月7日 7:07

答案

  • 我认为这样写要好一点

    private static lockobject=new object();

    public override void ExecuteCommand(PowerSession session, PowerControl.SuperSocketPower.BinaryRequestInfo requestInfo)
            {
                lock (lockobject) {


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    • 已标记为答案 lctk 2017年8月23日 6:41
    2017年8月8日 0:33
  • lctk:

    Shuanghua Li的方法照理而言是可以的,因为它内部定义了一个静态的object,然后进行锁。

    你可以给出截图告知具体lock(obj){……}之后仍然有多个线程进来的情况吗?我想看一看。


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    • 已标记为答案 lctk 2017年8月23日 6:41
    2017年8月8日 8:39
    版主
  • 查看是否是并发




    • 已标记为答案 lctk 2017年8月23日 6:41
    • 已编辑 [-] 2018年1月11日 11:34
    2017年8月9日 8:02

全部回复

  • 我认为这样写要好一点

    private static lockobject=new object();

    public override void ExecuteCommand(PowerSession session, PowerControl.SuperSocketPower.BinaryRequestInfo requestInfo)
            {
                lock (lockobject) {


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    • 已标记为答案 lctk 2017年8月23日 6:41
    2017年8月8日 0:33
  • 我认为这样写要好一点

    private static lockobject=new object();

    public override void ExecuteCommand(PowerSession session, PowerControl.SuperSocketPower.BinaryRequestInfo requestInfo)
            {
                lock (lockobject) {


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    ock(lockobject)也不可以,只是怎么回事啊?

    please verify my account

    2017年8月8日 4:19
  • lctk:

    请问你是什么类?具体怎么调用的?是WebForm,WinForm,WPF还是什么情况下出现此问题呢?


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月8日 4:39
    版主
  • lctk:

    请问你是什么类?具体怎么调用的?是WebForm,WinForm,WPF还是什么情况下出现此问题呢?


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    别人写的代码,用的supersocket框架,在他的command里面操作sqlite数据库,

    在command里面加上lock也不行,他这个方法是基于任务的IO回调方法,

    肯定是一下子回调好几个线程,加lock也不管用,怎么修改啊?


    please verify my account

    2017年8月8日 5:08
  • lctk:

    Shuanghua Li的方法照理而言是可以的,因为它内部定义了一个静态的object,然后进行锁。

    你可以给出截图告知具体lock(obj){……}之后仍然有多个线程进来的情况吗?我想看一看。


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    • 已标记为答案 lctk 2017年8月23日 6:41
    2017年8月8日 8:39
    版主
  • lctk:

    Shuanghua Li的方法照理而言是可以的,因为它内部定义了一个静态的object,然后进行锁。

    你可以给出截图告知具体lock(obj){……}之后仍然有多个线程进来的情况吗?我想看一看。


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report





    please verify my account

    2017年8月9日 6:28

  • please verify my account

    2017年8月9日 6:29
  • 你的截图想表明的意思是:一些工作线程仍然频繁调用Power……Execute多次是吧?

    如果是这样的话,请考虑哦:

    同一个函数可以被调用N次,这个无法修改。加lock可以保证同一个函数在同一个时刻最多只有一个线程调用(请仔细确认同一时刻你是多个还是仅有一个函数调用?你给出的调试截图只能证明说多个线程调用过函数N次,无法证明同一时刻到底调用了几次)。或许你在调试过程中看到的情况是棕黄色的线程调试背景线不断进来,但是经过lock的时候肯定变成了亮黄色的了(每次只允许来一个线程执行此方法)。

    或者给出你现在Execute的代码调试截图,谢谢!


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月9日 6:37
    版主
  • 你的截图想表明的意思是:一些工作线程仍然频繁调用Power……Execute多次是吧?

    如果是这样的话,请考虑哦:

    同一个函数可以被调用N次,这个无法修改。加lock可以保证同一个函数在同一个时刻最多只有一个线程调用(请仔细确认同一时刻你是多个还是仅有一个函数调用?你给出的调试截图只能证明说多个线程调用过函数N次,无法证明同一时刻到底调用了几次)。或许你在调试过程中看到的情况是棕黄色的线程调试背景线不断进来,但是经过lock的时候肯定变成了亮黄色的了(每次只允许来一个线程执行此方法)。

    或者给出你现在Execute的代码调试截图,谢谢!


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    怎么看同一时刻同一时刻到底调用了几次?

    或者给出你现在Execute的代码调试截图。

    这个就是啊,


    please verify my account

    2017年8月9日 6:41
  • 建议你在此函数里边使用NLog或者相关Log工具,打印出时间。如果你Lock使用正常,绝对不会出现同一时刻出现多个线程依次进来的(执行时间绝对不会重复,如果你在Web环境下,ThreadID会重复,因为ASP.NET基于ThreadPool为每次请求开辟新线程处理请求的)。

    public void ExecuteCommand(……)
    {
          lock(obj)
          {
                 Logger logger = Logger.Instance;
                 //Your Logic here
                 logger.WriteLog(DateTime.Now.ToString("HH:mm:ss:fff")+"ThreadID:"+Thread.CurrentThread.ManageID);  //Print the milliseconds
          }
    }

    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月9日 6:51
    版主
  • 查看是否是并发




    • 已标记为答案 lctk 2017年8月23日 6:41
    • 已编辑 [-] 2018年1月11日 11:34
    2017年8月9日 8:02
  • 对FAE9D91C-3F07-4090-91EB-E3F70E4D0617的补充,欢迎更正和讨论:

    1)如果框架使用同一个Instance的PowerExecute,那么每次线程进来必然锁住Instance自身,直到释放;所以每次进来一个线程,++后--。并发也是1.

    2)如果每一个线程都开辟一个Instance, 那么lock住Instance等于没有用(因为各个线程都用自己独立的Instance)。而且++或者--会被拆成几句话操作,所以不是原子化操作。静态变量m_count会出现不可预知的情况。

    >>在任何语言中只要整数类型的长度小于等于CPU寄存器的长度,对其进行的算术运算仅需一个指令周期,这样的类型具有天生的原子性。

    这个是说明单个运算符(比如赋值情况下,Int32 a = xxx;)不会出现有个别位数没有赋值的情况,是一下子被赋值的。

    但是++或者--是多次操作的运算符,拿“++”举例子:

    i++相当于CPU实际汇编指令(示例代码,假设EX是寄存器一类的东西):

    MOV EX I,
    
    INC EX
    
    MOV I EX

    这样的话,我们无法控制一个I在执行到这三个语句的某一个地方的时候被另外一个线程打断的问题。所以肯定不是原子操作。

    具体请参考:https://msdn.microsoft.com/zh-cn/library/aa691278(v=vs.71).aspx,尤其注意最后一句话:除专为该目的设计的库函数以外,对于增量或减量这类操作也不能保证进行原子的读、修改和写。


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report




    2017年8月9日 8:17
    版主
  • 咨询个问题,怎么在我这个command方法里面,

    查找同一时刻操作sqllite的线程的代码的位置,


    please verify my account

    2017年8月9日 8:27
  • 你的SQLLITE是第三方的吧?这个大概需要Sqllite的源码断电调试(比如获取sqllite的PDB文件,然后单步调试跟踪)。比较麻烦。

    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月9日 8:40
    版主
  • 咨询个问题,怎么在我这个command方法里面,

    查找同一时刻操作sqllite的线程的代码的位置,


    please verify my account

    或许需要关于Sqllite的PDB文件,断点调试的。不过多线程框架复杂,不好弄。

    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月9日 8:56
    版主
  • 没关系:)

    C++的确有,应该是C++11开始新增的类型吧?NET中用Internlocked.Increment/Decrement或者CAS操作代替。


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月9日 10:23
    版主
  • private volatile int _counter = 0; //volatile变量,表示该变量不要缓存,同时不希望编译器优化顺序。 private void Action(int i) {
    var copyCounter = _counter;

    for(;;) { if(Internlocked.CompareAndExchange(ref _counter,_copyCounter + 1,_copyCounter)
    {
    //消除了并发冲突,做你想做的事情……
    }
    } }


    ASP.NET Forum
    StackOverFlow
    FreeRice Donate
    Issues to report



    2017年8月9日 10:37
    版主
  • 我有个sqlite数据库,我想找到在command方法操作数据库的同时,其他的线程也在操作sqlite数据库的代码的位置

    please verify my account

    2017年8月10日 0:20
  • 有可能ExecuteCommand被并发调用,但是肯定是有别的函数(不是ExecuteCommand)在同一时刻操作数据库,想找到那个代码

    please verify my account

    2017年8月10日 1:07
  • 有源代码啊,但是不知道在哪里啊?不能通过快捷方式找到吗?

    please verify my account

    2017年8月10日 1:29
  • 针对楼主的问题,我这里有个想法。看起来ExecuteCommand这个函数有两个参数,session和requestInfo,那么这两个参数有没有什么变化。如果这两个参数中有什么32位整数类型或者是相当于指针的类型只在重复的回调相同,那么可以将其用=赋值给一个缓存量,然后每次对其进行判断,相同则不执行ExecuteCommand中的过程,不同则执行,因为读写都是原子操作的。如果不是整数类型,那么也可以加lock,然后进行判断。只要你的这个函数参数中有可以比对的地方就行。

    应该是每次都不同的(变化的),但是为啥有的时候相同的session执行了三四次,有时候只执行一次


    please verify my account

    2017年8月17日 7:03
  • 咨询个问题,怎么在我这个command方法里面,

    查找同一时刻操作sqllite的线程的代码的位置,


    please verify my account

    Hi,

    感谢你在MSDN论坛发帖。

    根据MSDN的规则,请不要在一个帖子下面,讨论更原帖不服的问题,你可以重新开贴。

    如果你的问题解决了,请及时标记有用的回复作为答案,这样会帮助遇到相同问题的人。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年8月22日 7:18
    版主