operation is executing and cannot be enqueued
我还注意到作为依赖关系的另一个 NSOperation 添加任何 NSOperation 时出现问题。如果我从我的代码中删除以下句子,称为 myOperation 的 dealloc 方法。
[otherOperation addDependency:myOperation];
@interface DownloadOperation:NSOperation
static DownloadOperation *downloadOperation; //期望构造工厂方法,不必每次调用都alloc
+ (DownloadOperation*)sharedDownloadOperation
{
if(downloadOperation==nil)
{
downloadOperation=[[self alloc]init];
}
return downloadOperation;
}
- (void)initWithURL:(NSString*)url delegate:(id<downloadFinishDelegate>)delegate//delegate是资料下载结束的回调
{
_webReachable=[WebConnectionWebConnect];
_delegate=delegate;
_enc =CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
_request=[[NSURLRequestrequestWithURL:[NSURLURLWithString:[url stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]retain];
self.XMLData=[NSMutableData data];
}
- (void)start //NSOperation添加到queue自动执行的函数
{
if([NSURLConnectioncanHandleRequest:_request]&&_webReachable)
{
_connection=[[NSURLConnectionconnectionWithRequest:_requestdelegate:self]retain];
while (_connection!=nil) {
[[NSRunLoop currentRunLoop]runMode:NSDefaultRunLoopMode beforeDate:[NSDatedistantFuture]];
}
}
else
{
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"无网络连接1" message:@"请检查网络" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
[alert release];
}
}
调用类:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.tableView.UserInteractionEnabled=NO;
[[DownloadOperation sharedDownloadOperation]initWithURL:@"http://www.bart.gov/dev/eta/bart_eta.xml" delegate:self];
[queue addOperation:[DownloadOperation sharedDownloadOperation]];
}
- (void)downloadFinish:(NSMutableData*)data //类:DownloadOperation下载完数据回调
{
self.tableView.userInteractionEnabled=YES;
}
结果执行一次正常,第二次出现错误:operation is executing and cannot be enqueued
后来也没解决,只好放弃静态变量,每次都重新创建DownloadOperation类的实例
在论坛上看到的类似案例,未验证,仅供参考
startAsynchronous] (我出现类似问题,[operation start] :operation is executing and cannot be enqueued) if for example the first request does not return
expected results.
The problem is that the second attempt to call startAsynchronous raise
an exception:
*** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '*** -[NSOperationQueue
addOperation:]: operation is finished and cannot be enqueued'
I'm pretty new to ASIHTTPRequest, so maybe I'm trying to do an
unsupported operation...
I'm doing something wrong? Should I create another request and then
call startAsynchronous on it?
- (void)viewDidLoad {
[super viewDidLoad];
// remote asynchronous call
NSURL *url = [self getConnectionURL];
mainHTTPRequest = [[ASIHTTPRequest requestWithURL:url] retain];
[mainHTTPRequest setDelegate:self];
[mainHTTPRequest startAsynchronous]; // ***** FIRST CALL *****
}
- (void)requestFinished:(ASIHTTPRequest *)request {
NSString *responseString = [request responseString];
BOOL repeat = [self checkIfRepeatNeeded:responseString];
if (repeat) {
[request startAsynchronous]; // ***** SECOND CALL *****
return;
}
// ... further processing...
}
> startAsynchronous] if for example the first request does not return
> expected results.
> The problem is that the second attempt to call startAsynchronous raise
> an exception:
>
> *** Terminating app due to uncaught exception
> 'NSInvalidArgumentException', reason: '*** -[NSOperationQueue
> addOperation:]: operation is finished and cannot be enqueued'
Yes, you cannot restart a request like this.
One option would be to make a copy of your request, and start that:
ASIHTTPRequest *newRequest = [[request copy] autorelease];
[newRequest startAsynchronous];
But, if you're just doing a simple GET request, you can just as easily create a new request with the same url.
问:
What if I have a model class with an ASIHTTPFormDataRequest *request ivar? Would something like this work?
- (void)dealloc {
[request clearDelegatesAndCancel];
[request release];
[super dealloc];
}
- (void)sendRequest {
[request clearDelegatesAndCancel];
[request release];
NSURL *url = [[NSURL alloc] initWithString:@"https://example.com/"];
request = [[ASIFormDataRequest alloc] initWithURL:url];
[url release];
request.delegate = self;
[request setPostValue:@"value1" forKey:@"key1"];
[request setPostValue:@"value2" forKey:@"key2"];
[request setPostValue:session forKey:@"iVarKey"];
[request startAsynchronous];
}
The first time i call -sendRequest, request will be nil. That should be fine. Any time after the first that I call it, the first two lines should reset the request correctly, right?
[request clearDelegatesAndCancel];
[request release];
Or, should I just create an ASIHTTPRequest category and define a method that does the above?
I'm asking because I want to write this code in four spots: dealloc, sendRequest, requestFinished, and requestFailed.
Wait, if I call [request release] will that call my delegate and/or queue’s failure delegate methods like [request cancel] does? If not, then can I just do [request release] in sendRequest, requestFinished, and requestFailed; and do both [request clearDelegatesAndCancel] and then [request release] in dealloc?
答:
You must call cancel and clear the delegate before you release your reference to the request. Calling release will not cause the request to immediately stop, so the delegate may be called later on (by which time it might not exist).
I'm on an older version, but I do:
request.delegate = nil; // after this line there are guaranteed to be no more calls to delegate
[request cancel];
[request release];
未验证:留着慢慢看
http://blog.csdn.net/proteas/article/details/7226173
近期将xcode升级到了4.2,SDK是 iOS5。在 iOS 5 下,以前可以正常工作的 NSOperation,会崩溃。崩溃的原因是:取消队列中的操作,但是该操作还没有开始。
解决这个问题的方法是:
在 start 方法中判断操作是否已经取消,如果取消,结束操作,没有取消,再执行操作。
在 cancel 方法中判断操作是否正在执行,如果在执行,结束操作,如果没有,修改操作的isCancelled状态。
头文件:
- #import <Foundation/Foundation.h>
- @interface FMURLRequest : NSOperation {
- BOOL _isReady;
- BOOL _isCancelled;
- BOOL _isExecuting;
- BOOL _isFinished;
- }
- - (void)cancel;
- @end
实现文件:
- #import "FMURLRequest.h"
- @interface FMURLRequest ()
- - (BOOL)isReady;
- - (BOOL)isExecuting;
- - (BOOL)isFinished;
- - (BOOL)isCancelled;
- - (BOOL)isConcurrent;
- - (void)start;
- - (void)finish;
- @end
- @implementation FMURLRequest
- - (id)init {
- if ((self = [super init])) {
- _isCancelled = NO;
- _isExecuting = NO;
- _isFinished = NO;
- _isReady = YES;
- }
- return self;
- }
- - (void)dealloc {
- [super dealloc];
- }
- #pragma -
- #pragma mark Operation Management & Super Class Methods
- - (BOOL)isReady {
- return _isReady;
- }
- - (BOOL)isExecuting {
- return _isExecuting;
- }
- - (BOOL)isFinished {
- return _isFinished;
- }
- - (BOOL)isCancelled {
- return _isCancelled;
- }
- - (BOOL)isConcurrent {
- return YES;
- }
- - (void)start {
- if (![NSThread isMainThread]) {
- [self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
- return;
- }
- [self willChangeValueForKey:@"isExecuting"];
- _isExecuting = YES;
- [self didChangeValueForKey:@"isExecuting"];
- if ([self isCancelled]) {
- [self finish];
- return;
- }
- // TODO: start operation
- }
- - (void)finish {
- [self willChangeValueForKey:@"isExecuting"];
- [self willChangeValueForKey:@"isFinished"];
- _isExecuting = NO;
- _isFinished = YES;
- [self didChangeValueForKey:@"isExecuting"];
- [self didChangeValueForKey:@"isFinished"];
- }
- - (void)cancel {
- [self willChangeValueForKey:@"isCancelled"];
- _isCancelled = YES;
- [self didChangeValueForKey:@"isCancelled"];
- if ([self isExecuting] == YES) {
- // TODO: clean resource
- [self finish];
- }
- }
- @end

NSOperation class
The NSOperation class is an abstract class you use to encapsulate the code and data associated with a single task.Because it is abstract, you do not use this class directly but instead subclass or use one of the system-defined subclasses (NSInvocationOperation orNSBlockOperation) to perform the actual task.An operation object is a single-shot object—that is, it executes its task once and cannot be used to execute it again.You typically execute operations by adding them to an operation queue (an instance of the NSOperationQueue class).An operation queue executes its operations either directly, by running them on secondary threads, or indirectly using the libdispatch libraryIf you do not want to use an operation queue, you can execute an operation yourself by calling its start method directly from your code. Executing operations manually does put more of a burden on your code, because starting an operation that is not in the ready state triggers an exception. The isReady method reports on the operation’s readiness.
key-value coding (KVC) and key-value observing (KVO)
Concurrent(并发) versus Non-Concurrent
If you plan on executing an operation object manually, instead of adding it to a queue, you can design your operation to execute in a concurrent or non-concurrent manner. Operation objects are non-concurrent by default. In a non-concurrent operation, the operation’s task is performed synchronously—that is, the operation object does not create a separate thread on which to run the task. Thus, when you call the start method of a non-concurrent operation directly from your code, the operation executes immediately in the current thread. By the time the start method of such an object returns control to the caller, the task itself is complete.
In contrast to a non-concurrent operation, which runs synchronously, a concurrent operation runs asynchronously. In other words, when you call the start method of a concurrent operation, that method could return before the corresponding task is completed. This might happen because the operation object created a new thread to execute the task or because the operation called an asynchronous function. It does not actually matter if the operation is ongoing when control returns to the caller, only that it could be ongoing.
If you always plan to use queues to execute your operations, it is simpler to define them as non-concurrent. If you execute operations manually, though, you might want to define your operation objects as concurrent to ensure that they always execute asynchronously. Defining a concurrent operation requires more work, because you have to monitor the ongoing state of your task and report changes in that state using KVO notifications. But defining concurrent operations can be useful in cases where you want to ensure that a manually executed operation does not block the calling thread.
For non-concurrent operations, you typically override only one method:
main
Into this method, you place the code needed to perform the given task. Of course, you should also define a custom initialization method to make it easier to create instances of your custom class. You might also want to define getter and setter methods to access the data from the operation. However, if you do define custom getter and setter methods, you must make sure those methods can be called safely from multiple threads.
If you are creating a concurrent operation, you need to override the following methods at a minimum:
start
isConcurrent
isExecuting
isFinished - (void)start
Begins the execution of the operation.
The default implementation of this method updates the execution state of the operation and calls the receiver’s main method. This method also performs several checks to ensure that the operation can actually run. - (void)main
Performs the receiver’s non-concurrent task.
The default implementation of this method does nothing. You should override this method to perform the desired task. In your implementation, do not invoke super.If you are implementing a concurrent operation, you are not required to override this method but may do so if you plan to call it from your custom start method. NSOperationQueue
The NSOperationQueue class regulates the execution of a set of NSOperation objects. After being added to a queue, an operation remains in that queue until it is explicitly canceled or finishes executing its task.You cannot directly remove an operation from a queue after it has been added. An operation remains in its queue until it reports that it is finished with its task.
operation is executing and cannot be enqueued的更多相关文章
- iOS NSOperation的使用
先给出NSOpetation的官方指导https://developer.apple.com/library/ios/documentation/Cocoa/Reference/NSOperation ...
- 解析AFNetWorking 网络框架(二)
转:http://blog.csdn.net/andy_jiangbin/article/details/17114989 接着前面写. 本帖先讲AFURLConnectionOperation,它是 ...
- SQL Performance Improvement Techniques(转)
原文地址:http://www.codeproject.com/Tips/1023621/SQL-Performance-Improvement-Techniques This article pro ...
- Concurrency in C# Cookbook 笔记
Pausing for a Period of TimeProblem:You need to (asynchronously) wait for a period of time. This can ...
- 使用任务Task 简化异步编程
使用任务简化异步编程 Igor Ostrovsky 下载代码示例 异步编程是实现与程序其余部分并发运行的较大开销操作的一组技术. 常出现异步编程的一个领域是有图形化 UI 的程序环境:当开销较大的操作 ...
- process monitor教程汇总
这是只一个简单的例子,当然还有更复杂的规则说明,可以参考一下列表里的规则. 最后说下 process monitor 到底有什么用? 除了那些电脑高手喜欢分析程序运行情况外, 还有那些编程 ...
- Method and apparatus for providing total and partial store ordering for a memory in multi-processor system
An improved memory model and implementation is disclosed. The memory model includes a Total Store Or ...
- 恢复误删除表黑科技之relay log大法
Preface In my previous blogs,I've demonstrated several mothods of how to rescue a dropped ta ...
- NSOperationQueue 和 NSOperation
The NSOperationQueue class regulates the execution of a set of NSOperation objects. After being adde ...
随机推荐
- How to Create Dump File for Applications
使用WinDBG这个工具,可以在应用程序异常终止或者无响应时获取它的尸体,以用来解剖研究. Creating Dump File 在Vista环境中抓取Dump文件很方便,在task man ...
- 基于visual Studio2013解决C语言竞赛题之1020订票
题目 解决代码及点评 /* 某航空公司规定:在旅游旺季7─9月份,若订票超过20张,优惠票价的15%,20张以下,优惠5%: 在旅游淡季1─5月.10月.11月份订票超过 ...
- display:inline-block的运用
在实习中做专题时,遇到的一个问题:建立一个宽度很长的一个页面,里面包含许多列.或许许多人认为直接设置float:left:不就行了 但是这个有一个问题,你必须把外面的div的宽度设置的很长已满足大于所 ...
- Go语言 关于go error处理风格的一些讨论和个人观点(上)
原创文章.转载请注明出处:server非业余研究-sunface 近期看谷歌go group里面有非常多讨论go error处理风格的问题,颇有启示.如今跟大家分享一下.首先请看一个提问: Hi fo ...
- hdu 4812 D Tree(树的点分治)
D Tree Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) Total ...
- EasyUI - Progressbar 进度条控件
效果: html代码: <div id="p" style="width:400px;"></div> JS代码: $(function ...
- 调用函数的ALV、面向对象的ALV设置带选择列
这个就是通过对应的选择列,实现对ALV数据的选择,在调用函数的ALV和面向对象的ALV实现方法存在差异,下面讲两者的方法:1)调用函数的ALV. 通过 SLIS_LAYOUT_ALV-BOX_FI ...
- 理清JavaScript正则表达式
理清JavaScript正则表达式--下篇 紧接:"理清JavaScript正则表达式--上篇". 正则在String类中的应用 类String支持四种利用正则表达式的方法.分别是 ...
- 开始翻译Windows Phone 8 Development for Absolute Beginners教程
Bob Tabor (LearnVisualStudio.NET)和Clint Rutkas (Microsoft/Channel9)合作推出了超过11小时的针对初学者的Windows Phone 8 ...
- BSGS_Baby steps giant steps算法
BSGS这个主要是用来解决这个题: A^x=B(mod C)(C是质数),都是整数,已知A.B.C求x. 在具体的题目中,C一般是所有可能事件的总数. 解: 设m = ceil(sqrt(C))(ce ...