6

Objective-Cメソッドではなく、C関数を使用して新しいスレッドを開始したいと思います。私は試した

[NSThread detachNewThreadSelector: @selector(func) toTarget: nil withObject: id(data)];

私が持っているところ

void func(void *data) {
   // ...
}

dataですが、から呼び出されvoid *たでランタイムクラッシュが発生しますobjc_msgSend

-[NSThread initWithTarget:selector:object:]

代わりに何ができますか?それも可能ですか?

4

5 に答える 5

10

あなた自身を転がしてください:

// In some .h file.  #import to make the extension methods 'visible' to your code.
@interface NSThread (FunctionExtension)
+(void)detachNewThreadByCallingFunction:(void (*)(void *))function data:(void *)data;
-(id)initWithFunction:(void (*)(void *))function data:(void *)data;
@end

// In some .m file.
@implementation NSThread (FunctionExtension)

+(void)startBackgroundThreadUsingFunction:(id)object
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  void (*startThreadFunction)(void *) = (void (*)(void *))[[object objectForKey:@"function"] pointerValue];
  void *startThreadData               = (void *)          [[object objectForKey:@"data"] pointerValue];

  if(startThreadFunction != NULL) { startThreadFunction(startThreadData); }

  [pool release];
  pool = NULL;
}

+(void)detachNewThreadByCallingFunction:(void (*)(void *))function data:(void *)data
{
  [[[[NSThread alloc] initWithFunction:function data:data] autorelease] start];
}

-(id)initWithFunction:(void (*)(void *))function data:(void *)data
{
  return([self initWithTarget:[NSThread class] selector:@selector(startBackgroundThreadUsingFunction:) object:[NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithPointer:function], @"function", [NSValue valueWithPointer:data], @"data", NULL]]);
}

@end

:私は上記のコードを書き、ここにパブリックドメインに配置しました。(この種のものが好きな弁護士もいます)それも完全にテストされていません!

スレッドエントリ関数もビットを作成することを保証できる場合は、いつでもNSAutoreleasePoolビットを削除できます...しかし、それは無害であり、速度のペナルティはまったくなく、任意のC関数の呼び出しがはるかに簡単になります。私はそれをそこに置いておくと言うでしょう。

そして、あなたはそれを次のように使うことができます:

void bgThreadFunction(void *data)
{
  NSLog(@"bgThreadFunction STARTING!! Data: %p", data);
}

-(void)someMethod
{
  // init and then start later...
  NSThread *bgThread = [[[NSThread alloc] initWithFunction:bgThreadFunction data:(void *)0xdeadbeef] autorelease];
  // ... assume other code/stuff here.
  [bgThread start];

  // Or, use the all in one convenience method.
  [NSThread detachNewThreadByCallingFunction:bgThreadFunction data:(void *)0xcafebabe];
}

実行時:

2009-08-30 22:21:12.529 test[64146:1303] bgThreadFunction STARTING!! Data: 0xdeadbeef
2009-08-30 22:21:12.529 test[64146:2903] bgThreadFunction STARTING!! Data: 0xcafebabe
于 2009-08-31T02:31:01.017 に答える
3

その関数を呼び出すだけのメソッドを使用してObjective-Cクラスを作成します。そのメソッドのセレクターを取得し、NSThreadAPIに渡します。

于 2009-08-30T22:11:34.187 に答える
3

それが可能かどうかはわかりませんが、すべてのObjective-Cメソッドには2つの暗黙的/非表示の引数とがselfあり_cmdます。IMP通常、次のtypedefようになります。

typedef id (*IMP)(id,SEL,...);

メソッドとセレクターをジェリーリグする場合は、次のようなメソッドが必要です。

void func (id self, SEL _cmd, void *firstParameter);

ただし、その後でも、セレクター名をランタイムに登録する必要があり、そのセレクターをメソッドに関連付ける必要がありますが、これはクラスごとに行われます(つまり、クラスは同じセレクターの異なる実装を持つことができます)名前)なので、少なくともダミークラスが必要です。

NSThreadさまざまなランタイムAPIを呼び出して単一のC関数を呼び出すよりも、ダミークラスとそのクラスのダミーインスタンスを作成する方がはるかに簡単です。

于 2009-08-30T23:54:23.713 に答える
1

必要がない場合は、直接POSIXインターフェイスNSThreadを使用してスレッドを開始することもできます。

于 2009-08-31T10:26:50.743 に答える
0

Objective-Cメソッドではなく、C関数を使用して新しいスレッドを開始したい

それなら、あなたはただ使ってみませんか:

  1. POSIXスレッド、
  2. GCD?

dispatch_async_f() (男)はまさにこの目的に適しています。

于 2014-05-18T06:14:02.747 に答える