简体   繁体   English

处理必须填充另一个类的实例中的字段的回调

[英]Dealing with a callback that must populate a field in another class's instance

I have a class SomeAction which implements ISomeAction (given to me), it has an async method that calls a non async void method which belongs to a class instance that is provided by a third party sdk. 我有一个实现ISomeAction的类SomeAction (给我),它有一个异步方法,该方法调用一个非异步void方法,该方法属于第三方sdk提供的类实例。 To handle the void in my async method, I use TaskCompletionSource which I intend on setting once I get the response from the third party. 为了处理异步方法中的void ,我使用TaskCompletionSource ,一旦收到第三方的响应,便打算进行设置。 The problem is, the response from the service is in the form of a callback which uses a class ThirdPartyCallbackClass that the third party has a defined interface for. 问题是,来自服务的响应采用了回调的形式,该回调使用了第三方为其定义接口的ThirdPartyCallbackClass类。

So how can I take the string passed back to the ThirdPartyCallbackClass and use it to update the TaskCompletionSource instance in SomeAction 所以,我怎么可以把string传递回ThirdPartyCallbackClass ,并用它来更新TaskCompletionSource的情况下SomeAction

Here is the code (forgive any typos): 这是代码(可避免任何拼写错误):

public class SomeAction : ISomeAction
{
    private TaskCompletionSource<string> fbtcs;

    public async Task<string> someTask()
    {
        var accessToken = await SomeAsyncMethod();
        return accessToken;
    }

    private async Task<string> SomeAsyncMethod()
    {
        fbtcs = new TaskCompletionSource<string>();
        TaskClass tc = new TaskClass();
        tc.CallThirdParty();

        return await fbtcs.Task;
    }
}

public class TaskClass
{
    public void CallThirdParty()
    {
        ThirdParty tp = new ThirdParty();
        var somePayload = "payload";
        ThirdPartyCallbackClass callback = new ThirdPartyCallbackClass();
        tp.VoidMethodWithCallback(somePayload, callback);
    }
}

public class ThirdPartyCallbackClass : IThirdPartyDefinedCallback
{
    public void OnSuccess(string p)
    {
        //At this point I want to take p and use it to update SomeAction's fbtcs instance string. Is my design wrong or is there a strategy for dealing with this?
       //If this was in my `SomeAction` instance I would try to do something like...

       //fbtcs.TrySetResult(p);
    }
}

If ThirdParty::VoidMethodWithCallback is a synchronous method then you don't need to use TaskCompletionSource at all, you can call synchronous methods directly in an async or Task<TResult> -returning method: 如果ThirdParty::VoidMethodWithCallback是同步方法,则根本不需要使用TaskCompletionSource ,可以直接在asyncTask<TResult>返回方法中直接调用同步方法:

public class SomeAction : ISomeAction
{
    public Task<String> SomeTaskAsync()
    {
        return Task.FromResult( this.SomeMethod() );
    }

    private String SomeMethod()
    {
        String value = new TaskClass().CallThirdParty();
        return value;
    }
}

public class TaskClass
{
    private class CallbackContainer : IThirdPartyDefinedCallback
    {
        public String ReturnedValue;

        public void OnSuccess(String p)
        {
            this.ReturnedValue = p;
        }
    }

    public String CallThirdParty()
    {
        ThirdParty tp = new ThirdParty();
        var somePayload = "payload";

        CallbackContainer callbackContainer = new CallbackContainer();

        tp.VoidMethodWithCallback( somePayload, callbackContainer );

        return callbackContainer.ReturnedValue;
    }
}

In the event that SomeTaskAsync is called directly from a UI thread or some other thread that should not block, then use Task.Run to run the synchronous method on a Thread-pool thread: 如果直接从UI线程或不应阻塞的其他线程中直接调用SomeTaskAsync ,请使用Task.Run在线程池线程上运行同步方法:

public class SomeAction : ISomeAction
{
    public Task<String> SomeTaskAsync()
    {
        return Task.Run( (Func<String>)this.SomeMethod );
    }
}

Note the standard (ie Microsoft) naming convention in .NET is to always have Async at the end of the name of any method which ultimately executes asynchronously (it doesn't necessarily need to be flagged with the async modifier: it could pass-through a Task<T> from another call, for example). 请注意,.NET中的标准(即Microsoft)命名约定始终是在最终最终异步执行的任何方法名称的末尾都带有Async (它不一定需要用async修饰符标记:它可以通过例如,另一个调用中的Task<T> )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM