нужна помощь в доступе к данным, поступающим с обратного вызова C # .NET - PullRequest
0 голосов
/ 16 ноября 2010

Я в своем уме пытаюсь решить эту проблему.

У меня есть функция в классе как таковая

public class ReceiveData
{
    Dataprovider provider = new DataProvider();

    public void ResponseData()
    {
        foreach(string anItem in TheList)
        {
            // AllData function is declared in class DataProvider
            string result = provider.AllData(anItem); 
        }

        //do something
    }
}

Это просто.Тем не менее, что бы я сделал, если бы функции AllData приходилось выполнять асинхронные вызовы функций для получения данных?

Значение, скажем

public class DataProvider 
{
    MyServiceClient client = new MyServiceClient();

    public string AllData (string  myItem)
    {
        client.FormattedDataCompleted += new EventHandler<FormattedDataCompletedEventArgs>(client_FormattedDataCompleted);
        client.FormattedDataAsync(myItem);
    }

    void client_FormattedDataCompleted(object sender, FormattedDataCompletedEventArgs e)
    {
        // here's where the response comes back.
    }

Как вы можете видеть, теперь я не могу просто вызвать функцию AllData ивернуть данные напрямую.

Итак, что мне нужно сделать в функции ResponseData, чтобы убедиться, что я вызываю функцию AllItem и получаю данные обратно из обратного вызова.Обратите внимание, что в этой функции есть цикл, поэтому мне нужно, чтобы все параметры, которые я отправил через цикл, получили соответствующий ответ.

Один из подходов, которые я пробовал, заключался в использовании класса AutoResetEvent.

Я определил обработчик для этого как AutoResetEvent handle = new AutoResetHandle (false);

, затем я добавляю handle.WaitOne () сразу после асинхронного вызова.и в обратном вызове добавлен handle.Set ();

Однако приложения застревают в handle.WaitOne ().Так что я не могу понять, почему это происходит.

Теперь у меня есть теоретическая идея посмотреть, могу ли я иметь обработчик событий в обратном вызове и обработчик событий в классе RecieveData, и если эти двое будут общаться, я смогу получить данные.Но я потратил некоторое время, пытаясь узнать больше об обработчиках событий, но не освоил его.

Так есть ли у кого-нибудь другой подход, идеи?Спасибо!

Ответы [ 2 ]

0 голосов
/ 16 ноября 2010

Вам просто нужно использовать делегата и вызвать BeginInvoke.Затем вы можете установить метод обратного вызова для захвата результата вызова делегата.

public class ReceiveData
{
    private List<string> TheList = new List<string>
    {
        "1", "2", "3"
    };

    dynamic provider = new ExpandoObject();

    public void ResponseData()
    {
        foreach (string anItem in TheList)
        {
            // AllData function is declared in class DataProvider
            Func<string, string> asyncAllData = provider.AllData;
            asyncAllData.BeginInvoke(anItem, AllDataDone, null);
        }
        //do something
    }

    private void AllDataDone(IAsyncResult iar)
    {
        AsyncResult ar = (AsyncResult)iar;
        var del = (Func<string, string>)ar.AsyncDelegate;
        // here's your result
        string result = del.EndInvoke(iar);
    }
}
0 голосов
/ 16 ноября 2010

Добро пожаловать в асинхронную модель.Вы должны заново продумать, как вы вызываете методы, когда вы используете многопоточность.

У вас есть несколько вариантов:

  • Разделить метод, в котором вы делаете вызов, надве половины;в первой половине вызовите AllData, сделайте НИЧЕГО, иначе вы можете обойтись без объекта ответа, а затем выйдите из текущего метода.Когда асинхронный вызов завершится, он вызовет ваш обработчик, где вы должны выполнить все операции из исходного метода, требующие ответа.

  • В обработчике события для завершения асинхронного вызова,установите свойство, которое указывает, что вызов завершен, и поместите данные в свойство где-нибудь также.В функции, которая запускает вызов, в точке, где вы просто не можете продолжить выполнение, пока вызов не завершится, подождите в цикле while, чтобы завершить вызов, опрашивая свойство и прерывая его, как только он указывает, что вызов завершен (выВозможно, вам понадобится также Thread.Yield () в цикле, который вы будете вызывать, когда еще не получили ответ, чтобы убедиться, что вы не блокируете другие потоки, делая более важные вещи, чем ожидание)

  • Оберните ваш асинхронный вызов в класс, который предоставляет синхронный метод.Класс-оболочка будет иметь логику, аналогичную интеграции асинхронного вызова в ваш метод.Он выполнит вызов, дождется ответа и вернет этот ответ, как если бы это был обычный синхронный вызов метода.

Помните, что асинхронный вызов дает вашему вызывающему потоку возможностьвыполнять другую работу, пока выполняется вызов.Воспользуйтесь этим в полной мере, если это возможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...