这与我之前提出的问题有关,但不同之处,我认为我会把它扔进一个新问题.我有一些代码在自定义队列上运行异步,然后在完成时在主线程上执行完成块.我想围绕这种方法编写单元测试.我的方法MyObject看起来像这样.
+ (void)doSomethingAsyncThenRunCompletionBlockOnMainQueue:(void (^)())completionBlock {
dispatch_queue_t customQueue = dispatch_queue_create("com.myObject.myCustomQueue", 0);
dispatch_async(customQueue, ^(void) {
dispatch_queue_t currentQueue = dispatch_get_current_queue();
dispatch_queue_t mainQueue = dispatch_get_main_queue();
if (currentQueue == mainQueue) {
NSLog(@"already on main thread");
completionBlock();
} else {
dispatch_async(mainQueue, ^(void) {
NSLog(@"NOT already on main thread");
completionBlock();
});
}
});
Run Code Online (Sandbox Code Playgroud)
}
我投入了主队列测试以获得额外的安全性,但它总是能够击中dispatch_async.我的单元测试如下所示.
- (void)testDoSomething {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
void (^completionBlock)(void) = ^(void){
NSLog(@"Completion Block!");
dispatch_semaphore_signal(sema);
};
[MyObject doSomethingAsyncThenRunCompletionBlockOnMainQueue:completionBlock];
// Wait for async code to finish
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); …Run Code Online (Sandbox Code Playgroud) 在C++ 11中,有许多新的随机数生成器引擎和分发函数.它们是否安全?如果您在多个线程之间共享一个随机分布和引擎,它是否安全并且您是否仍会收到随机数?我正在寻找的场景是这样的,
void foo() {
std::mt19937_64 engine(static_cast<uint64_t> (system_clock::to_time_t(system_clock::now())));
std::uniform_real_distribution<double> zeroToOne(0.0, 1.0);
#pragma omp parallel for
for (int i = 0; i < 1000; i++) {
double a = zeroToOne(engine);
}
}
Run Code Online (Sandbox Code Playgroud)
使用OpenMP或
void foo() {
std::mt19937_64 engine(static_cast<uint64_t> (system_clock::to_time_t(system_clock::now())));
std::uniform_real_distribution<double> zeroToOne(0.0, 1.0);
dispatch_apply(1000, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(size_t i) {
double a = zeroToOne(engine);
});
}
Run Code Online (Sandbox Code Playgroud)
使用libdispatch.
是否可以在单元测试tearDown中重置dispatch_once代码的状态?
我认为如果我们的单元测试可以从一个非常干净的状态运行会很好,但我们正在努力使用dispatch_once和一些使用dispatch进行的单例测试.
使用Grand Central Dispatch,可以轻松地在非主线程上执行耗时的任务,避免阻止主要攻击并保持UI响应.只需dispatch_async在全局并发队列上使用并执行任务即可.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// code
});
Run Code Online (Sandbox Code Playgroud)
然而,听起来好得令人难以置信,因为这个通常有它们的缺点.在我们的iOS应用程序项目中使用了很多之后,最近我们发现它有64个线程限制.一旦我们达到限制,应用程序将冻结/挂起.通过暂停应用程序与Xcode,我们可以看到主线程由semaphore_wait_trap.
在网上搜索确认其他人也遇到了这个问题,但到目前为止还没有找到解决方案.
达到调度线程硬限制:64(同步操作中阻塞的调度线程太多)
另一个问题计算器证实了这一问题时使用发生dispatch_sync和dispatch_barrier_async太.
问题:
由于Grand Central Dispatch有64个线程限制,有没有解决方法?
提前致谢!
Apple的Grand Central Dispatch参考文献称:
"......如果你的应用程序需要在系统的Unix级别运行 - 例如,如果它需要操作文件描述符,Mach端口,信号或定时器.GCD不仅限于系统级应用程序,而是在你之前将它用于更高级别的应用程序时,您应该考虑Cocoa中提供的类似功能(通过NSOperation和块对象)是否更易于使用或更适合您的需求."
对于高级应用程序,我实际上无法想到这种情况,其中GCD的使用是强制性的,并且可以/不应该使用NSOperation.
有什么想法吗?
concurrency objective-c grand-central-dispatch ios objective-c-blocks
我有一些数据计算方法(让它是"myMethod:"),我想将调用移动到另一个线程,因为我不想阻止我的主UI功能.所以,开始研究如何在另一个线程上调用我的方法.据我所知,目前有很多不同的方法可以做到这一点.这是一个清单:
a)使用纯线程(自iOS 2.0起可用):
[NSThread detachNewThreadSelector:@selector(myMethod:) toTarget:self withObject:_myParamsArray];
Run Code Online (Sandbox Code Playgroud)
b)使用简单的快捷方式(从iOS 2.0开始提供).可从继承的NSObject获得,但该方法也属于NSThread类:
[self performSelectorInBackground:@selector(myMethod:) withObject:_myParamsArray];
Run Code Online (Sandbox Code Playgroud)
c)使用Grand Central Dispatch队列的新方法(自iOS 4.0起可用):
dispatch_async(dispatch_get_global_queue(0, 0),
^ {
[self myMethod:_myParamsArray];
});
Run Code Online (Sandbox Code Playgroud)
d)不知何故,使用一些类,如NSOperation,NSBlockOperation或NSOperationQueue,虽然不确定如何完成它(一些例子将被赞赏)
目前,我使用了案例"b",但对其利弊和其他相关建议充满好奇.
更新:e)还找到了执行类似线程的另一种方法 - 运行循环.以下是苹果文档的摘录:
运行循环是一个事件处理循环,用于计划工作并协调传入事件的接收.运行循环的目的是在有工作时保持线程忙,并在没有线程时让线程进入休眠状态.
恕我直言,或多或少你正在处理相同的任务 - 如何在单独的线程上调用你的方法进行异步操作.
更新2:已经有一些NSInvocationOperation和NSOperationQueue和恕我直言的经验,这是非常方便的.根据Apple文档,GCD和NSOperations是实现多线程的首选方式.此外,NSOperations从iOS 4.0开始在GCD上运行.简而言之,您实例化NSIvocationOperation(作为对您的方法的调用)然后实例化NSOperationQueue并将调用添加到队列.NSOperationQueue足够聪明,你可以实例化多个NSIvocationOperation对象(包装方法调用)并将它们实例化为NSOperationQueue.其余的都有保证.NSOperationQueue确定执行调用所需的并行线程数(NSInvocationOperation)并为您处理.它可以在线程A上执行第一次调用,然后在线程B上执行第二次调用,在线程C上执行第三次,在线程B上执行第三次调用,因此您不必担心这一点.但是如果你愿意,你可以告诉NSOperationQueue最大线程如何用于执行调用(例如1),但我没有必要这样做.默认情况下,所有任务都在主线程以外的位置执行,因此默认情况下操作队列是异步的.此外,如果要在严格队列中执行方法调用(每个包装在单独的NSInvocationOperation中),则可以添加依赖项,因此NSOperationQueue将保留方法调用顺序.这是一个例子:
// wrap your method call into NSInvocationOperation object
NSInvocationOperation *currentOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(yourMethodCall) object:nil];
// _sharedOperationQueue is a shared NSOperationQueue
// get all executing operations from the queue and get the last operation
_lastOperation = [[_sharedOperationQueue operations] lastObject];
// check if _lastOperation is …Run Code Online (Sandbox Code Playgroud) concurrency multithreading objective-c grand-central-dispatch ios
我目前正在玩Grand Central Dispatch并发现了一个名为的课程DispatchWorkItem.文档似乎有点不完整,所以我不确定以正确的方式使用它.我创建了以下代码段,并期待一些不同的东西.我希望在调用cancel它之后该项目将被取消.但由于某种原因,迭代仍在继续.我有什么想法我做错了吗?代码似乎对我来说很好.
@IBAction func testDispatchItems() {
let queue = DispatchQueue.global(attributes:.qosUserInitiated)
let item = DispatchWorkItem { [weak self] in
for i in 0...10000000 {
print(i)
self?.heavyWork()
}
}
queue.async(execute: item)
queue.after(walltime: .now() + 2) {
item.cancel()
}
}
Run Code Online (Sandbox Code Playgroud) 我无法暂停gcd查询.以下是一些演示此问题的代码:
static dispatch_queue_t q=nil;
static void test(int a){
if(q){
dispatch_suspend(q);
dispatch_release(q);
q=nil;
}
q=dispatch_get_global_queue(0,0);
dispatch_async(q,^ {
while(1){NSLog(@"query %d",a);sleep(2);}
});
}
int main(int argc, const char* argv[]){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
test(1);
//blah blah blah
test(2);
while(1){}
[pool release];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试做的是在第二次调用函数测试时暂停,释放和重新初始化查询q,但显然我的代码是错误的,并且查询q的两个实例都继续运行.
非常感谢您的帮助,谢谢.
我搜索了各种来源,但并不真正理解使用NSThreads和GCD 之间的区别.我是OS X平台的新手,所以我可能完全误解了这个.
从我在线阅读的内容来看,GCD似乎与基本线程(POSIX NSThreads等)完全相同,同时添加了更多技术术语("块").它似乎只是使基本的线程创建系统(创建线程,运行函数)过于复杂.
GCD究竟是什么?为什么它会优于传统的线程?应该何时使用传统线程而不是GCD?最后是否有GCD奇怪语法的原因?("块"而不是简单地调用函数).
我在Mac OS X 10.6.8 Snow Leopard上,我不是为iOS编程 - 我正在为Mac编程.我在Cocoa中使用Xcode 3.6.8,创建了一个GUI应用程序.
macos cocoa multithreading objective-c grand-central-dispatch
目前我正在使用NSThread另一个线程缓存图像.
[NSThread detachNewThreadSelector:@selector(cacheImage:) toTarget:self withObject:image];
Run Code Online (Sandbox Code Playgroud)
交替:
[self performSelectorInBackground:@selector(cacheImage:) withObject:image];
Run Code Online (Sandbox Code Playgroud)
或者,我可以使用 NSOperationQueue
NSInvocationOperation *invOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(cacheImage:) object:image];
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperation:invOperation];
Run Code Online (Sandbox Code Playgroud)
有没有理由改变NSThread?GCD是iPhone上发布的第四个选项,但除非有显着的性能提升,否则我宁愿坚持使用适用于大多数平台的方法.
根据@ Jon-Eric的建议,我选择了NSOperationQueue/ NSOperation子类解决方案.它工作得很好.该NSOperation班是足够灵活,你可以调用,块或定制子类使用它,这取决于你的需求.无论您如何创建自己,NSOperation都可以在准备运行时将其放入操作队列中.如果需要,这些操作可以作为您放入队列的对象,也可以作为独立的异步方法运行.由于您可以轻松地同步运行自定义操作方法,因此测试非常简单.
我在一些项目中使用了相同的技术,因为我问了这个问题,我对它保持我的代码和我的测试干净,有条理和快乐异步的方式感到高兴.
A +++++++++++++++++++++++++
objective-c ×7
ios ×3
concurrency ×2
c++ ×1
c++11 ×1
cancellation ×1
cocoa ×1
iphone ×1
macos ×1
nsthread ×1
openmp ×1
swift ×1