简体   繁体   English

如何从异步方法获取复杂类型

[英]How to get a complex type from async method

 public ObservableCollection<Offer> ModelPersons
    {
        get
        {

            return _persons;
        }


        set
        {
            _persons = value;

            RaisePropertyChanged(() => ModelPersons);
        }
    }

// How can I get the ObservableCollection<Person> from the Task<ObservableCollection<Person>> ? //如何从Task<ObservableCollection<Person>>获取ObservableCollection<Person> Right now it's complaining about can not convert source type Task<Observable<Person>> to Observable<Person> 现在它抱怨无法将源类型Task<Observable<Person>> to Observable<Person>

  private void GetPersonOrders()
    {
        ModelPersons = _service.GetPersonOrders();
    }

in Service Class: 在服务类:

  private ObservableCollection<Person> _modelPersons;


    public async Task<ObservableCollection<Person>> GetPersonOrders()
    {

        var req =
           WebRequest.Create(
              "http....")
               as HttpWebRequest;

        if (req == null) return null;
        req.KeepAlive = false;
        req.Method = "GET";
        req.ContentType = "text/xml; encoding='utf-8'";

        WebResponse response = req.GetResponse();
        Stream receiveStream = response.GetResponseStream();

        Encoding encode = Encoding.GetEncoding("utf-8");
        string message = null;
        if (receiveStream != null)
            using (var readStream = new StreamReader(receiveStream, encode))
            {
                var result = new char[256];
                int count = await readStream.ReadAsync(result, 0, 256);
                while (count > 0)
                {
                    var value = new String(result, 0, count);
                    message += value;
                    count = await readStream.ReadAsync(result, 0, 256);
                }


                var stringReader = new StringReader(message);
                _modelPersons= new ObservableCollection<Person>();
                var xmlTextReader = new XmlTextReader(stringReader);
                xmlTextReader.WhitespaceHandling = WhitespaceHandling.None;
                Person person = null;
                string element = "";
                while (xmlTextReader.Read())
                {
                    if (xmlTextReader.NodeType == XmlNodeType.Element)
                    {
                        element = xmlTextReader.Name;
                    }

                    else if (xmlTextReader.NodeType == XmlNodeType.Text)
                    {
                        switch (element)
                        {
                            case "name":
                                person = new Person { Name = xmlTextReader.Value };
                                _modelPersons.Add(person);
                                break;



                        }
                    }
                }
            }
        return _modelPersons;
    }

I recommend you use the NotifyTaskCompletion type from my AsyncEx library . 我建议你使用我的AsyncEx库中NotifyTaskCompletion类型

Then your code will look like this: 然后你的代码将如下所示:

private INotifyCompletion<ObservableCollection<Offer>> _persons;
public INotifyCompletion<ObservableCollection<Offer>> ModelPersons
{
  get { return _persons; }
  set
  {
    _persons = value;
    RaisePropertyChanged(() => ModelPersons);
  }
}

private void GetPersonOrders()
{
  ModelPersons = NotifyCompletion.Create(_service.GetPersonOrdersAsync());
}

And your data binding will change from ModelPersons to ModelPersons.Result . 您的数据绑定将从ModelPersons更改为ModelPersons.Result

Further recommended reading: 进一步推荐阅读:

Since your method returns a Task<ObservableCollection<Person>> you can get the result of the task via Result property. 由于您的方法返回Task<ObservableCollection<Person>>您可以通过Result属性获取任务的Result

private void GetPersonOrders()
{
    ModelPersons = _service.GetPersonOrders().Result;
}

Keep in mind however, that accessing the Result property will block the calling thread until the task completes, ie until you will receive the WebResponse . 但请记住,访问Result属性将阻止调用线程,直到任务完成,即直到您将收到WebResponse

Another way would be to attach a continuation task to the task returned by your method using ContinueWith . 另一种方法是使用ContinueWith将延续任务附加到方法返回的任务。 The continuation will set the property to the value returned from task. continuation将属性设置为从task返回的值。

private void GetPersonOrders()
{
    _service.GetPersonOrders()
        .ContinueWith(t => ModelPersons = t.Result);
}

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

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