如何停止使用dispatch_async创build的线程?

我想强行停止由dispatch_async创build的线程,如果它的使用时间过长,例如超过5分钟。 通过在互联网上search,我觉得有人认为没有办法阻止线程,有没有人知道?

在我的想象中,我想创build一个NSTimer来在指定的时间过后停止线程。

 + (void)stopThread:(NSTimer*)timer { forcibly stop the thread??? } + (void)runScript:(NSString *)scriptFilePath { [NSTimer scheduledTimerWithTimeInterval:5*60 target:self selector:@selector(stopThread:) userInfo:nil repeats:NO]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [LuaBridge runLuaFile:scriptFilePath]; }); } 

我的runLuaScript方法:

 + (void)runLuaFile:(NSString *)filePath { lua_State *L = luaL_newstate(); luaL_openlibs(L); int error2 = luaL_dofile(L, [filePath fileSystemRepresentation]); if (error2) { fprintf(stderr, "%s", lua_tostring(L, -1)); lua_pop(L, 1); } lua_close(L); } 

亲爱的@Martin R,我应该使用这样的lstop,当我想停止线程,只需调用stopLuaRunning方法?

 static lua_State *L = NULL; + (void)runLuaFile:(NSString *)filePath { L = luaL_newstate(); luaL_openlibs(L); int error2 = luaL_dofile(L, [filePath fileSystemRepresentation]); if (error2) { fprintf(stderr, "%s", lua_tostring(L, -1)); lua_pop(L, 1); } lua_close(L); } + (void)stopLuaRunning:(lua_State *L) { lua_sethook(L, NULL, 0, 0); luaL_error(L, "interrupted!"); } 

你不能杀死一个正在运行的块。 你必须以asynchronous工作的方式实现runLuaFile ,并且可以取消。

例如,如果通过NSTask运行脚本,则可以使用terminateterminate运行时间过长的任务。

NSOperation可能没有帮助,因为cancel依赖于操作是“合作”:操作必须定期检查是否已被取消。 这不会停止正在运行的runLuaFile方法。

更新:从检查Lua解释器的源代码“lua.c”,在我看来,你可以使用lua_sethook取消正在运行的脚本。

一个非常简单的实现(使用Lua状态的静态variables)将是:

 static lua_State *L = NULL; + (void)runLuaFile:(NSString *)filePath {  L = luaL_newstate();  luaL_openlibs(L);  int error2 = luaL_dofile(L, [filePath fileSystemRepresentation]);  if (error2) {    fprintf(stderr, "%s", lua_tostring(L, -1));    lua_pop(L, 1);  }  lua_close(L); L = NULL; } static void lstop (lua_State *L, lua_Debug *ar) { lua_sethook(L, NULL, 0, 0); luaL_error(L, "interrupted!"); } + (void)stopLuaRunning { if (L != NULL) lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); } 

一个更优雅的解决scheme是将Lua状态存储在类的实例variables中,并使用runLuaFilestopLuaRunning实例方法代替类方法。

你应该使用NSOperationNSOperationQueue因为它们支持取消操作,所以你的操作可以检查它是否被取消,而你的定时器只是调用cancel操作。

通过互联网search,我得到了一个虽然没有办法阻止线程,有没有人知道?

不要打扰 停止不是你的。 如果你有一个队列的引用,那么你可以调用dispatch_release ,它会在适当的时候被销毁,但是你不会在全局队列中这样做。

杀死该线程只会杀死队列池中的一个线程,应该被视为未定义的行为。

如果你想控制一个线程的生命周期,创build自己的线程并与其运行循环进行交互。 但是确保你的程序正常地从其实现中返回 – 不要仅仅因为它不适合你或者永远不会返回而杀死那些东西。 马丁R提到了这将发生 – 你的任务应该支持超时,取消,或其他方式来阻止自己在任务stream氓的事件。

温恩也提到了一个好的中间地带。

使用NSOperation和NSOperationQueue。

这是一个漫长而有用的指南。

http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues

在这种情况下,你的关键点是有重写主要的例子。

 @interface MyLengthyOperation: NSOperation @end @implementation MyLengthyOperation - (void)main { // a lengthy operation @autoreleasepool { for (int i = 0 ; i < 10000 ; i++) { // is this operation cancelled? if (self.isCancelled) break; NSLog(@"%f", sqrt(i)); } } } @end 

注意循环中间的if(self.isCancelled)。

这是pipe理后台操作的“现代”iOS方法,无需创build自己的线程并直接pipe理它们。