问题:要创建一个接受用户输入但在几秒钟后超时的程序(现在说它是2秒)。
方法:我创建了两个线程,一个用于等待用户输入(inputThread
带tid[0]
),另一个用于休眠2秒(sleepThread
with tid[1]
)。我从另一个线程的例程中取消一个线程,如下所示:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_t tid[2];
void* inputThread()
{
int n;
printf("Enter number:");
// wait for input; if input is given then go ahead and cancel the sleeper thread.
scanf("%d",&n);
// cancel the sleeper thread
pthread_cancel(tid[1]);
printf("Got value:%d\n",n);
}
void* sleepThread()
{
// sleep for 2 seconds and cancel the input thread.
sleep(2);
// cancel the input thread
pthread_cancel(tid[0]);
printf("\nNo value entered!\n");
}
int main(int argc, char const *argv[])
{
int r1,r2,r3,r4;
// input taking thread
r1 = pthread_create(&tid[0],NULL,inputThread,NULL);
// sleeping thread
r2 = pthread_create(&tid[1],NULL,sleepThread,NULL);
r3 = pthread_join(tid[0],NULL);
r4 = pthread_join(tid[1],NULL);
return 0;
}
截至目前,该计划按预期运作。
但我的朋友说,保证无法正常工作,因为取决于线程的安排方式。他试着向我解释同样的事情,但我无法理解。他还说pthread_cancel
只是取消线程的请求,可能不会成功。
所以有人可以指出潜在的错误和最佳做法,以避免相同。为了保证计划的正常运行,我们也不胜感激。
答案 0 :(得分:3)
您的朋友关于pthread_cancel
是取消线程的请求的部分是正确的,并且可能永远不会成功。
关于日程安排的部分,您需要提供他所拥有的参数。
要解决您的问题,您可以放弃一起使用线程(除非这是您的分配要求),并将select
与read
一起使用。
这将使解决方案不可移植(仅符合POSIX),但pthreads
无论如何也不可移植。
select
允许您等待文件描述符(在本例中为0
),以便数据可用于读取。它还允许您设置超时。
fd_set set;
FD_ZERO(&set);
FD_SET(0, &set);
struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;
int ret = select(1, &set, NULL, NULL, &timeout);
if (ret == 1) {
char buffer[20];
int n;
read(0, buffer, 20);
sscanf(buffer, "%d", &n);
printf("Got value:%d\n",n);
} else {
printf("Time out\n");
}
答案 1 :(得分:1)
你的朋友是对的,我认为他的意思是你不能假设知道哪个线程先运行/完成。 但是在2秒内肯定会安排两个线程,所以thread1有时间要求用户输入并等待一点输入。
我没有看到大问题,如果没问题,那就不要太担心。
然而,您可以使用SIGALRM信号而不是sleep
,但它涉及掩码,需要花费更多时间来理解(我正在做this project:检查task2
函数并掩盖它如果你想要一个例子,请使用。)
答案 2 :(得分:0)
pthread_cancel函数调用线程上的线程取消处理程序,然后,一旦它们返回,将调用线程的析构函数,这反过来将终止线程。
因为它是一个请求,它可能会失败,由pthread_cancel
指示返回一个非零整数。
如果您使用两个以上的线程来执行此操作,或者更多线程在同一进程中访问stdin,则可能会让线程等待访问stdin,从而导致所需的行为被延迟。