• 6800阅读
  • 12回复

如何在线程运行中,弹出对话框让用户选择,并暂停线程 [复制链接]

上一主题 下一主题
离线stlcours
 

只看楼主 倒序阅读 楼主  发表于: 2016-09-04
就好比有一个线程在拷贝很多文件,但是忽然发现有一个文件已经存在了,请用户确认是否覆盖,此时需要弹出对话框,并暂停线程(Windows拷贝文件就是这样的)。
等到用户选择了yes或者no之后,继续进行拷贝。这种情况应该如何写代码?

我考虑使用如下方案:

if (文件已经存在) {
  lock;
  emit 信号; // 让GUI弹出一个对话框
  lock; // 此时必定卡住,因为前面已经锁过一次了
}
然后在用户点击确认按钮后,两次解锁,不知道这种方案可行吗?大家有没有什么更好的方案?因为我觉得主动连续两次上锁怪怪的,从来只见过一次上锁。



离线ysu533

只看该作者 1楼 发表于: 2016-09-04
这里为什么要上锁,个人觉得不但不需要2个锁,一个都不是必要的,这个线程除了拷贝,要干什么了?

另外你线程是怎么写的? movetothread,还是什么?
离线stlcours

只看该作者 2楼 发表于: 2016-09-04
回 ysu533 的帖子
ysu533:这里为什么要上锁,个人觉得不但不需要2个锁,一个都不是必要的,这个线程除了拷贝,要干什么了?
另外你线程是怎么写的? movetothread,还是什么?
 (2016-09-04 06:35) 

我在网上搜了一下,都是使用锁,或者用变量进行空循环进行控制。我这线程,就是挨个拷贝文件啊,没有干别的事情。但是是否覆盖原有的文件,总该问问吧。

另外,我这线程就是继承QThread,没有采用movetothread。最近努力学习movetothread方法,可总是感觉不适应,不知道为什么这种方法却是官方的推荐方法?
离线ysu533

只看该作者 3楼 发表于: 2016-09-04
回 stlcours 的帖子
stlcours:我在网上搜了一下,都是使用锁,或者用变量进行空循环进行控制。我这线程,就是挨个拷贝文件啊,没有干别的事情。但是是否覆盖原有的文件,总该问问吧。
另外,我这线程就是继承QThread,没有采用movetothread。最近努力学习movetothread方法,可总是感觉不适应,不知道为什么这 .. (2016-09-04 13:43)

官方文档早改了,继承不是不能用啊,movethread更简单啊, 一会我简单的给你写个

离线ysu533

只看该作者 4楼 发表于: 2016-09-04
加入copy对像是你用来执行拷贝操作的,

QThread * thread = new QThread();

copy->moveToThread(thread);

thread->start();

connect(copy, SIGNAL(fileExist()), xx, SLOT(XXXX()));
copy->start(files); 开始拷贝文件
---------------------

void Copy::start(const QStringList &files)  // 开始拷贝这些文件
{
    QTimer::singleShot(0, this, SLOT(copy())); // 这里不执行实际拷贝,通过信号槽间接调用 copy
}

void Copy::copy(const QStringList &files)
{
   foreach(QString file, files) {
      if(存在) {
         emit fileExist(file);
         break;
       } else {
          拷贝文件
      }
     emit copyFinished();
   }
}


这样就不用考虑跨线程的问题了。
离线stlcours

只看该作者 5楼 发表于: 2016-09-04
谢谢你辛苦写了这么多代码,但是没有回答到问题的实质。emit fileExist(file)以后,是应该要把线程暂停住(卡住?),等待用户选择后再进行下一步的操作。你如何保证这一点呢?
离线ysu533

只看该作者 6楼 发表于: 2016-09-04
回 stlcours 的帖子
stlcours:谢谢你辛苦写了这么多代码,但是没有回答到问题的实质。emit fileExist(file)以后,是应该要把线程暂停住(卡住?),等待用户选择后再进行下一步的操作。你如何保证这一点呢? (2016-09-04 15:19)

大哥,这都没看明白啊, emit fileexist之后有个break;已经跳出拷贝了,

会执行XXXX()这个槽。

如果这个槽如果什么也不做,那么拷贝就终止了

如果你需要跳过,你只需要稍微修改下代码 把files 这个变量保存下就行了。

然后你自己实现下 skip, retry, overwrite, 实现跳过,重试,覆盖的功能就行了。

不需要你去额外控制线程。 这就是movetothread的好处。

离线ysu533

只看该作者 7楼 发表于: 2016-09-04
回 stlcours 的帖子
stlcours:
谢谢你辛苦写了这么多代码,但是没有回答到问题的实质。emit fileExist(file)以后,是应该要把线程暂停住(卡住?),等待用户选择后再进行下一步的操作。你如何保证这一点呢?


今天没什么事,写了比较完整的例子,见附件,有什么问题,可以交流,编译需要qt5,

实现功能是将一个目录中的文件拷贝到另一个目录,已存在文件,可以跳过继续复制,或者覆盖文件,或是终止复制。

CopyFile CopyFile.zip (4 K) 下载次数:22
离线stlcours

只看该作者 8楼 发表于: 2016-09-04
回 ysu533 的帖子
ysu533:今天没什么事,写了比较完整的例子,见附件,有什么问题,可以交流,编译需要qt5,
实现功能是将一个目录中的文件拷贝到另一个目录,已存在文件,可以跳过继续复制,或者覆盖文件,或是终止复制。
....... (2016-09-04 18:11) 

谢谢。全是lamda,家里的XP机子太旧了没法运行,明天到公司再试试。

不过我还是没有明白你的意思,怎么能离开break呢?根据用户的指示,再决定是否继续处理后面的文件,而你这样就是完全退出了,似乎不对啊。。。
离线ysu533

只看该作者 9楼 发表于: 2016-09-04
回 stlcours 的帖子
stlcours:谢谢。全是lamda,家里的XP机子太旧了没法运行,明天到公司再试试。
不过我还是没有明白你的意思,怎么能离开break呢?根据用户的指示,再决定是否继续处理后面的文件,而你这样就是完全退出了,似乎不对啊。。。 (2016-09-04 18:18)

你试试,就知道对不对了。当然,代码结构不一定要这么写。 你可以故意制造冲突, 比如在第一个目录还没复制完,马上在ui上操作复制第二个目录,你会发现,并不会覆盖第一个目录的相关变量, 比如dircopy中的 fromList 和 toList。

我离开了,后面又回来了, 除非用户选择了 abort


只看该作者 10楼 发表于: 2016-09-05
新手回答圣骑士的对话看着果真很爽
!!!
离线ysu533

只看该作者 11楼 发表于: 2016-09-05
回 哥依然潇洒 的帖子
哥依然潇洒:新手回答圣骑士的对话看着果真很爽
!!! (2016-09-05 08:51) 

啥意思?
离线gasdfrewq

只看该作者 12楼 发表于: 2017-01-22
信号可以用阻塞模式等待界面执行完成之后再执行吧?
我之前这么用过,不知道适不适合你这个情况
快速回复
限100 字节
 
上一个 下一个