V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
sunhk25
V2EX  ›  问与答

C#如何确保单线程的执行顺序

  •  
  •   sunhk25 · 2017-05-01 10:19:36 +08:00 · 2100 次点击
    这是一个创建于 2769 天前的主题,其中的信息可能已经有所发展或是发生改变。
    A.exe 中调用单线程 B.exe 来生成一个文件,文件名为秒时间例如 HHmms.txt
    当在 A 中快速点击调用 B 的时候,如何确保点击的顺序跟执行的顺序一致?
    A 程序无法修改,我有在 B 中添加 mutex 和 Thread.Sleep(1000)来确保执行一次要一秒,
    但是下一个执行的任务却是随机的,无法保证按点击顺序来执行
    第 1 条附言  ·  2017-05-01 11:22:35 +08:00

    原来的程序使用C++实现的,执行起来貌似也是按点击顺序来执行的,但是在C#用Mutex类无法达到效果

    CArkMutex::~CArkMutex()
    {
    	if (bCreate) {
    		ReleaseMutex(m_hMutex);
    		CloseHandle(m_hMutex);
    	}
    	if (m_hProc != NULL)
    		CloseHandle( m_hProc);
    }
    
    bool CArkMutex::Create(const char *pszName)
    {
    	if (bCreate)
    		return false;
    
    	m_hMutex = CreateMutex(0, FALSE, pszName);
    	if (m_hMutex) {
    		bCreate = true;
    	}
    
    	return bCreate;
    }
    
    bool CArkMutex::Enter()
    {
    	if (!bCreate)
    		return false;
    
    	WaitForSingleObject(m_hMutex, INFINITE);
    
    	return true;
    }
    
    bool CArkMutex::Leave()
    {
    	if (!bCreate)
    		return false;
    
    	ReleaseMutex(m_hMutex);
    
    	return true;
    }
    
    第 2 条附言  ·  2017-05-01 11:23:04 +08:00

    原来的程序使用C++实现的,执行起来貌似也是按点击顺序来执行的,但是在C#用Mutex类无法达到效果

    CArkMutex::~CArkMutex()
    {
    	if (bCreate) {
    		ReleaseMutex(m_hMutex);
    		CloseHandle(m_hMutex);
    	}
    	if (m_hProc != NULL)
    		CloseHandle( m_hProc);
    }
    
    bool CArkMutex::Create(const char *pszName)
    {
    	if (bCreate)
    		return false;
    
    	m_hMutex = CreateMutex(0, FALSE, pszName);
    	if (m_hMutex) {
    		bCreate = true;
    	}
    
    	return bCreate;
    }
    
    bool CArkMutex::Enter()
    {
    	if (!bCreate)
    		return false;
    
    	WaitForSingleObject(m_hMutex, INFINITE);
    
    	return true;
    }
    
    bool CArkMutex::Leave()
    {
    	if (!bCreate)
    		return false;
    
    	ReleaseMutex(m_hMutex);
    
    	return true;
    }
    
    第 3 条附言  ·  2017-05-10 13:14:07 +08:00
    ------------------------
    由于是进程间执行顺序的问题,采用了第三方工具把待处理的任务保存到队列后然后再顺序执行。
    具体做法是用 IPC 进程间通信,调用 B 时在 B 中把执行内容放到主程序的远程对象队列 Queue<string>中
    然后在主程序中再从队列里面拿出来了调用 B (在 B 中判断是主程序调用还是 A 中调用)
    11 条回复    2017-05-10 13:15:45 +08:00
    momocraft
        1
    momocraft  
       2017-05-01 10:25:27 +08:00   ❤️ 1
    能不能说一下确保的目的是什么?
    sunhk25
        2
    sunhk25  
    OP
       2017-05-01 10:39:16 +08:00
    @momocraft 生成的文件是类似 HHmmss.txt 这样的以秒为单位的文件名,所以一秒内多次执行时需要控制进程等待
    ipconfiger
        3
    ipconfiger  
       2017-05-01 10:50:53 +08:00   ❤️ 1
    A 中每次点击都先用一个线程安全的 FIFO 对列存起来, 然后在一个独立的线程中一个一个取出来去调用 B
    zmj1316
        4
    zmj1316  
       2017-05-01 10:52:45 +08:00   ❤️ 1
    A 里面搞一个队列,点一次就向队列里丢一个,另外 A 开一个新线程,每次从队列里面取一个出来调用 B,并且阻塞等待 B 结束,这样可以保证只有一个 B 在执行,并且顺序和队列一致。

    如果只用单线程也可以实现,阻塞改成 poll 就行了
    sunhk25
        5
    sunhk25  
    OP
       2017-05-01 11:13:10 +08:00
    @ipconfiger @zmj1316 在 A 里实现的话确实可以,问题是 A 程序无法修改,如何在 B 中实现
    ipconfiger
        6
    ipconfiger  
       2017-05-01 11:40:17 +08:00
    B 里面也可以做到, 思路类似, 不过因为 B 是被调用方, 所以需要用额外的跨进程存储结构来维持对列
    Valyrian
        7
    Valyrian  
       2017-05-01 11:42:22 +08:00 via iPad   ❤️ 1
    Lockfile
    sunhk25
        8
    sunhk25  
    OP
       2017-05-01 16:41:53 +08:00
    @ipconfiger 试了几种队列调用方式(lock,ThreadPool),在 B 中测试时可以保证顺序,但是从 A 里调用 B 时,顺序还是随机。请问在 B 中如何管理额外的跨进程队列
    sunhk25
        9
    sunhk25  
    OP
       2017-05-01 16:43:22 +08:00
    @Valyrian Lockfile 能解决随机的问题吗
    Valyrian
        10
    Valyrian  
       2017-05-02 01:48:46 +08:00
    @sunhk25 可以吧,在文件内容里做一些手脚
    sunhk25
        11
    sunhk25  
    OP
       2017-05-10 13:15:45 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   929 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 20:58 · PVG 04:58 · LAX 12:58 · JFK 15:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.