I want to forcibly stop the thread created by dispatch_async
if its in use for too much time, for example pass over 5 minutes. By searching over the internet, I got some one thought there was no way to stop the thread, does any one know that?
In my imagine, I want to create a NSTimer
to stop the thread when time specified passed.
+ (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];
});
}
My runLuaScript method:
+ (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);
}
Dear @Martin R, should I use lstop like that, and when I want to stop the thread, just call stopLuaRunning
method?
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!");
}
Don't bother; It's not yours to stop. If you have a reference to a queue, then you can call
dispatch_release
and it will be destroyed at the appropriate time, but you would not do this with the global queue.Killing that thread would just kill a thread in the queue's pool and should be considered as good as undefined behavior.
If you want to control a thread's lifetime, create your own thread and interact with its run loop. But do ensure your programs return from their implementations normally -- don't just kill stuff because it isn't working for you or never returning. Martin R mentioned how this would happen -- your task should support timeout, cancellation, or another means to stop itself in the event the task has gone rogue.
Wain's also mentioned a good middle ground.
You cannot kill a running block. You have to implement
runLuaFile
in a way that it works asynchronously and can be cancelled.For example if running the script is done via
NSTask
, you can useterminate
to kill the task if it is running too long.NSOperation
will probably not help becausecancel
relies on the operation to be "cooperative": the operation has to check regularly if it has been cancelled. That will not stop the runningrunLuaFile
method.UPDATE: From inspecting the source code "lua.c" of the Lua interpreter, it seems to me that you can cancel a running script using
lua_sethook
.A very simple implementation (using a static variable for the Lua state) would be:
A more elegant solution would use store the Lua state in an instance variable of the class and make
runLuaFile
andstopLuaRunning
instance methods instead of class methods.Use NSOperation and NSOperationQueue.
Here is a long, but helpful guide.
http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues
The key point for you in this case, is there example of overriding main.
Notice the if (self.isCancelled) in the middle of the loop.
This is the "modern" iOS way of managing background operations without creating your own threads and managing them directly.
You should use
NSOperation
andNSOperationQueue
as they have built in support for cancellation so your operation can check if it's cancelled and your timer just callscancel
on the operation.