C# 将基于回调的类包装为异步类

C# 将基于回调的类包装为异步类,c#,.net,asynchronous,callback,C#,.net,Asynchronous,Callback,我正在引用一个类,该类使用回调而不是异步操作执行各种苛刻的操作。例如: class CallbackClass : SomeSdkCallbacks { public void RequestData() { // We call this to request some data. // After some time, this will trigger OnDataReturned to be called } public

我正在引用一个类,该类使用回调而不是异步操作执行各种苛刻的操作。例如:

class CallbackClass : SomeSdkCallbacks
{
    public void RequestData()
    {
        // We call this to request some data.
        // After some time, this will trigger OnDataReturned to be called
    }

    public void OnDataReturned(DataObject data)
    {
        // This will be called automatically with returned data via SomeSdkCallbacks
    }
}
在这个类中有许多这种类型的结构实例

我想做的是围绕这个类创建一个包装器类,简化它的使用。我现在要说的结构是:

class MyWrapperClass
{
    CallbackClass CallbackClass;

    public MyWrapperClass()
    {
        this.CallbackClass = new CallbackClass();
    }

    public DataObject GetData()
    {
        this.CallbackClass.RequestData();

        // Somehow wait until this.CallbackClass.OnDataReturned is called?

        // Somehow get the data that would be passed in to this.CallbackClass.OnDataReturned()???
    }
}
将“回调”体系结构包装成单个异步方法的最佳方法是什么

编辑:为了澄清,理想情况下,我希望将其打包到一个方法中,该方法可以在一个请求中返回数据。请参阅示例中的
MyWrapperClass.GetData()
方法,了解我的理想结构


编辑2:我知道这种理想的架构形式不好。不幸的是,这就是我所要求的结构。

在您的情况下,您可以在CallBackClass上添加一些事件。 就像这里:

class CallbackClass : SomeSdkCallbacks
{
    public event Action<object> DataReturnedEvent;
    public void RequestData()
    {
        // We call this to request some data.
        // After some time, this will trigger OnDataReturned to be called
    }
    public void OnDataReturned(DataObject data)
    {
        DataReturnedEvent?.Invoke(data);
    }
}

我想这就是你想要的:

        class CallbackClass<T>
        {
            private TaskCompletionSource<T> task = new TaskCompletionSource<T>();

            public void RequestData()
            {
               
            }

            public void OnDataReturned(T data)
            {
                task.SetResult(data);
            }

            public Task<T> Task { get { return task.Task; } }
        }

        class MyWrapperClass
        {
            public Task<DataObject> GetData()
            {
                var cls = new CallbackClass<DataObject>();

                cls.RequestData();

                return cls.Task;
            }
        }
class回调类
{
私有TaskCompletionSource任务=新TaskCompletionSource();
public void RequestData()
{
}
返回的公共无效数据(T数据)
{
task.SetResult(数据);
}
公共任务任务{get{return Task.Task;}
}
类MyWrapperClass
{
公共任务GetData()
{
var cls=newcallbackclass();
cls.RequestData();
返回cls.Task;
}
}

请注意,每个操作都必须创建
TaskCompletionSource
,这样就不会对两个不同的调用使用同一个操作。有了它,您可以使用
async
关键字。可能会有点帮助。

谢谢。问题是,如果调用
MyWrapperClass.GetData()
,则该调用实际上不会返回数据。你能想出一种方法让
GetData()
自己请求并返回数据吗?或者这是一种不好的做法吗?这是达到目标的最简单的方法。等等,只是从GetData()方法获取数据没有意义。您不知道它何时发生,等待会冻结当前线程。如果您的系统在调用GetData()之后能够工作,并且稍后系统会对有关传递数据的事件做出反应,那么这是一种更好的方法。另一种方法是使用asybc/await模式,但这是一种更为困难的方法,因为您必须根据EAP模式()创建类型,否则一个关于EAP方法的链接以上的开头(如OnDataReturned),按照惯例是引发事件的方法,而不是处理事件的方法。您的体系结构似乎有点错误。另外,在方法
public void OnDataReturned(DataObject data)
中没有任何东西可以让您以任何方式截获此数据。用你展示的代码做你要求的是不可能的。您需要为我们提供一个有效的解决方案。@Enigmativity很好,但是该方法正在实现
SomeSdkCallbacks
接口,我无法控制该接口。除非您对某些内容有控制权,否则这是一个无法回答的问题。请告诉我们你能控制什么,不能控制什么。请提供一个谜团,你显然不明白我的问题。但别担心,菲利普理解并回答了。
        class CallbackClass<T>
        {
            private TaskCompletionSource<T> task = new TaskCompletionSource<T>();

            public void RequestData()
            {
               
            }

            public void OnDataReturned(T data)
            {
                task.SetResult(data);
            }

            public Task<T> Task { get { return task.Task; } }
        }

        class MyWrapperClass
        {
            public Task<DataObject> GetData()
            {
                var cls = new CallbackClass<DataObject>();

                cls.RequestData();

                return cls.Task;
            }
        }