<!--
{
  "availability" : [
    "iOS: 2.0.0 -",
    "iPadOS: 2.0.0 -",
    "macCatalyst: 13.1.0 -",
    "macOS: 10.5.0 -",
    "tvOS: 9.0.0 -",
    "visionOS: 1.0.0 -",
    "watchOS: 2.0.0 -"
  ],
  "documentType" : "symbol",
  "framework" : "ObjectiveC",
  "identifier" : "/documentation/ObjectiveC/NSObject-swift.class/perform(_:on:with:waitUntilDone:)",
  "metadataVersion" : "0.1.0",
  "role" : "Instance Method",
  "symbol" : {
    "kind" : "Instance Method",
    "modules" : [
      "Objective-C Runtime",
      "ObjectiveC"
    ],
    "preciseIdentifier" : "c:objc(cs)NSObject(im)performSelector:onThread:withObject:waitUntilDone:"
  },
  "title" : "perform(_:on:with:waitUntilDone:)"
}
-->

# perform(_:on:with:waitUntilDone:)

Invokes a method of the receiver on the specified thread using the default mode.

```
func perform(_ aSelector: Selector, on thr: Thread, with arg: Any?, waitUntilDone wait: Bool)
```

## Parameters

`aSelector`

A [Selector](https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html#//apple_ref/doc/uid/TP40008195-CH48) that identifies the method to invoke. The method should not have a significant return value and should take a single argument of type id, or no arguments.

`thr`

The thread on which to execute `aSelector`.

`arg`

The argument to pass to the method when it is invoked. Pass `nil` if the method does not take an argument.

`wait`

A Boolean that specifies whether the current thread blocks until after the specified selector is performed on the receiver on the specified thread. Specify [`YES`](/documentation/ObjectiveC/YES) to block this thread; otherwise, specify [`NO`](/documentation/ObjectiveC/NO) to have this method return immediately.

    If the current thread and target thread are the same, and you specify [`YES`](/documentation/ObjectiveC/YES)     for this parameter, the selector is performed immediately on the current thread. If you specify [`NO`](/documentation/ObjectiveC/NO)    , this method queues the message on the thread’s run loop and returns, just like it does for other threads. The current thread must then dequeue and process the message when it has an opportunity to do so.

## Discussion

You can use this method to deliver messages to other threads in your application. The message in this case is a method of the current object that you want to execute on the target thread.

This method queues the message on the run loop of the target thread using the default run loop modes—that is, the modes associated with the <doc://com.apple.documentation/documentation/Foundation/RunLoop/Mode/common> constant. As part of its normal run loop processing, the target thread dequeues the message (assuming it is running in one of the default run loop modes) and invokes the desired method.

You cannot cancel messages queued using this method. If you want the option of canceling a message on the current thread, you must use either the [`perform(_:with:afterDelay:)`](/documentation/ObjectiveC/NSObject-swift.class/perform(_:with:afterDelay:)) or [`perform(_:with:afterDelay:inModes:)`](/documentation/ObjectiveC/NSObject-swift.class/perform(_:with:afterDelay:inModes:)) method.

### Special Considerations

This method registers with the runloop of its current context, and depends on that runloop being run on a regular basis to perform correctly. One common context where you might call this method and end up registering with a runloop that is not automatically run on a regular basis is when being invoked by a dispatch queue. If you need this type of functionality when running on a dispatch queue, you should use <doc://com.apple.documentation/documentation/Dispatch/dispatch_after> and related methods to get the behavior you want.

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)