【发布时间】:2017-10-01 02:39:57
【问题描述】:
我刚刚开始接触并发编程。很可能我的问题很常见,但由于我找不到一个好名字,我无法谷歌它。
我有一个 C++ UWP 应用程序,我尝试在其中应用 MVVM 模式,但我猜该模式甚至是 UWP 都不相关。
首先,我有一个暴露操作的服务接口:
struct IService
{
virtual task<int> Operation() = 0;
};
当然,我提供了一个具体的实现,但与本次讨论无关。该操作可能需要长时间运行:它发出一个 HTTP 请求。
然后我有一个使用该服务的类(同样,省略了不相关的细节):
class ViewModel
{
unique_ptr<IService> service;
public:
task<void> Refresh();
};
我使用协程:
task<void> ViewModel::Refresh()
{
auto result = co_await service->Operation();
// use result to update UI
}
刷新函数每分钟在计时器上调用一次,或者响应用户请求。我想要的是:如果在启动或请求新的操作时已经在进行刷新操作,则放弃第二个操作并等待第一个操作完成(或超时)。换句话说,我不想将所有对 Refresh 的调用排队 - 如果一个调用已经在进行中,我宁愿跳过一个调用,直到下一个计时器滴答。
我的尝试(可能非常天真)是:
mutex refresh;
task<void> ViewModel::Refresh()
{
unique_lock<mutex> lock(refresh, try_to_lock);
if (!lock)
{
// lock.release(); commented out as harmless but useless => irrelevant
co_return;
}
auto result = co_await service->Operation();
// use result to update UI
}
在原帖后编辑:我注释掉了上面代码 sn-p 中的行,因为它没有区别。问题还是一样。
当然,断言失败:unlock of unowned mutex。我猜问题出在mutex by unique_lock 析构函数的unlock 上,它发生在协程的延续和不同的线程上(除了它最初被锁定的线程)。
使用 Visual C++ 2017。
【问题讨论】:
-
@WhozCraig,我没试过,但我愿意接受任何建议——你能举个代码示例吗?
-
真正幼稚的解决方案:
std::atomic<bool> running. -
你不认为问题更多在于你试图释放一个你知道没有锁定的锁吗?
-
制作一个静态实例计数器怎么样?
-
@UKMonkey,不,问题不在于锁的释放。原因很多,所以我们只能说即使删除了线路,问题仍然存在。我相应地编辑了问题。
标签: c++ multithreading c++11 visual-c++ visual-c++-2017