如何停止使用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
运行脚本,则可以使用terminate
来terminate
运行时间过长的任务。
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中,并使用runLuaFile
和stopLuaRunning
实例方法代替类方法。
你应该使用NSOperation
和NSOperationQueue
因为它们支持取消操作,所以你的操作可以检查它是否被取消,而你的定时器只是调用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理它们。