Jan*_*lis 5 c++ multithreading visual-c++ c++11 visual-c++-2017
我刚刚进入并发编程.最有可能我的问题很常见,但由于我找不到一个好名字,我不能谷歌.
我有一个C++ UWP应用程序,我尝试应用MVVM模式,但我想这种模式甚至是UWP是不相关的.
首先,我有一个公开操作的服务接口:
struct IService
{
virtual task<int> Operation() = 0;
};
Run Code Online (Sandbox Code Playgroud)
当然,我提供了一个具体的实现,但它与此讨论无关.该操作可能长时间运行:它发出HTTP请求.
然后我有一个使用该服务的类(同样,省略了不相关的细节):
class ViewModel
{
unique_ptr<IService> service;
public:
task<void> Refresh();
};
Run Code Online (Sandbox Code Playgroud)
我使用协同程序:
task<void> ViewModel::Refresh()
{
auto result = co_await service->Operation();
// use result to update UI
}
Run Code Online (Sandbox Code Playgroud)
每分钟在计时器上调用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
}
Run Code Online (Sandbox Code Playgroud)
在原帖后编辑:我在上面的代码片段中注释掉了这一行,因为它没有任何区别.问题仍然存在.
但当然断言失败了:unlock of unowned mutex.我想这个问题是unlock的mutex通过unique_lock析构函数,这发生在协程的延续,并在不同的线程(比它最初锁定在一个除外).
使用Visual C++ 2017.
使用std::atomic_bool:
std::atomic_bool isRunning = false;
if (isRunning.exchange(true, std::memory_order_acq_rel) == false){
try{
auto result = co_await Refresh();
isRunning.store(false, std::memory_order_release);
//use result
}
catch(...){
isRunning.store(false, std::memory_order_release);
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
两个可能的改进:包装isRunning.store在 RAII 类中并使用std::shared_ptr<std::atomic_bool>if 的生命周期(如果atomic_bool是范围内的)。
| 归档时间: |
|
| 查看次数: |
368 次 |
| 最近记录: |