调用第三方API的Discover异步方法后,如何等待完成再执行自定义代码?
Got it, let's solve this problem cleanly. The key here is to convert that callback-based async Discover method into an awaitable task, so you can wait for it to finish before running your reusable custom code—without having to stuff that code into the callback itself.
Step 1: Define Your Reusable Custom Code
First, extract your business logic into a standalone method that you can call anywhere:
// This is your reusable code, callable in any scenario public void MyReusableCustomLogic(string apiResponse) { // Your custom business logic here Console.WriteLine($"Processing API response: {apiResponse}"); // ... add more of your specific code here }
Step 2: Wrap Discover with TaskCompletionSource
Use TaskCompletionSource<T> to bridge the gap between the callback pattern and modern async/await (or synchronous waiting if you need it):
Async/Await Approach (Recommended for Non-Blocking Code)
This is the best option for most cases, as it avoids blocking threads:
public async Task ExecuteDiscoverAndRunLogic(string key) { var completionSource = new TaskCompletionSource<string>(); // Call Discover with a minimal callback that only signals completion myServiceClient.Discover(key, response => { // Pass the API response to the completion source completionSource.SetResult(response); // Optional: Handle invalid responses by setting an exception if (string.IsNullOrWhiteSpace(response)) { completionSource.SetException(new InvalidOperationException("Received empty or invalid response from API")); } return true; // Match the API's required callback return type }); // Wait for Discover to finish and retrieve the response string apiResponse = await completionSource.Task; // Now run your reusable custom logic MyReusableCustomLogic(apiResponse); }
Synchronous Approach (For Blocking Scenarios)
If you absolutely need to run this synchronously (note: avoid this in UI threads to prevent freezing), use Task.Result:
public void ExecuteDiscoverSyncAndRunLogic(string key) { var completionSource = new TaskCompletionSource<string>(); myServiceClient.Discover(key, response => { completionSource.SetResult(response); return true; }); // Block until Discover completes string apiResponse = completionSource.Task.Result; // Run your reusable code MyReusableCustomLogic(apiResponse); }
Why This Works
- The callback passed to
Discoveronly handles signaling completion (and passing the response), keeping it focused and separate from your business logic. - Your
MyReusableCustomLogicstays independent—you can call it from this flow, or any other scenario where you need that code. - You get explicit control over waiting for
Discoverto finish before proceeding, ensuring all necessary underlying operations are complete before your custom code runs.
内容的提问来源于stack exchange,提问作者Some User

