.net - Observable 和 Webclient 获取 csv

标签 .net csv webclient system.reactive

我的 lightswitch 应用程序中有一个函数,可以从网站下载 csv 文件,我想使用 Rx 框架重写该文件,并提供同步调用它的可能性。

下面提供的是旧函数和新函数的代码片段。然而,新函数不起作用,对 ParseCSV 的调用永远不会发生。我想知道为什么,如果有更好的解决方案,请随时提供。

旧代码:

private void ObservableCollection<Data> collection;
public ObservableCollection<Data> GetData(string url, ObservableCollection<Data> targetCollection)
{

collection = targetCollection;
if (!string.IsNullOrEmpty(url))
{
    WebClient wc = new WebClient();
    wc.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenReadCompleted_ParseCSV);
    wc.OpenReadAsync(new Uri(url));
}
return collection;
}

private void OpenReadCompleted_ParseCSV(object sender, OpenReadCompletedEventArgs e)
{

if (e.Error != null) return;

var webClient = sender as WebClient;
if (webClient == null) return;

try
{
    using (StreamReader reader = new StreamReader(e.Result))
    {
        string contents = reader.ReadToEnd();
        ...
    }
}
catch (Exception ex)
{
    System.Diagnostics.Debug.WriteLine("Error parsing CSV!\n" + ex.Message);
}

}

新代码(带 Rx):

private void ObservableCollection<Data> collection;
public ObservableCollection<Data> GetData(string url, ObservableCollection<Data> targetCollection)
{
collection = targetCollection;
if (!string.IsNullOrEmpty(url))
{
    var result = Observable.FromEventPattern<OpenReadCompletedEventHandler, OpenReadCompletedEventArgs>
                 (
                    ev => webClient.OpenReadCompleted += ev,
                    ev => webClient.OpenReadCompleted -= ev
                 )
                 .Select(o => o.EventArgs.Result)
                 .FirstOrDefault()
                 .ParseCSV();

    // Call the Async method
    webClient.OpenReadAsync(new Uri(url));
}
return collection;
}

private void ParseCSV(this Stream stream)
{
try
{
    using (StreamReader reader = new StreamReader(e.Result))
    {
        string contents = reader.ReadToEnd();
        ...
    }
}
catch (Exception ex)
{
    System.Diagnostics.Debug.WriteLine("Unable to get history data!\n" + ex.Message);
}
}

最佳答案

很难知道你想要什么(我认为你试图简化在 StackOverflow 上发布的代码,并且在翻译中丢失了很多内容),但我认为对此我没有什么可以改变的。

我注意到的一件事是您正在主线程上解析结果。您可能会这样做是有原因的,但您可能会考虑以下几点:

//Note the void here. Is your intention to return a new collection or contribute
//to an existing one? I assumed the latter and changed the method to be more clear
//that this method causes side effects.
public void GetData(string url, ObservableCollection<Data> targetCollection)
{
        var result = Observable
            .FromEventPattern<OpenReadCompletedEventHandler, OpenReadCompletedEventArgs>
            (
                ev => webClient.OpenReadCompleted += ev,
                ev => webClient.OpenReadCompleted -= ev
            )
            .Select(o => ParseCSV(o.EventArgs.Result));

    result.Subscribe(targetCollection.Add);
    webClient.OpenReadAsync(new Uri(url));
}

//This method now returns a Data object read from a Stream
private static Data ParseCSV(Stream stream)
{
    try
    {
        using (StreamReader reader = new StreamReader(stream))
        {
            string contents = reader.ReadToEnd();
            //...
            return data;
        }
    }
    catch (Exception ex)
    {
        //Use Exception.ToString(). You get error and stack trace information
        //For this error as well as any inner exceptions. Nice!
        System.Diagnostics.Debug.WriteLine("Unable to get history data!\n" + ex.ToString());
    }
    return null;
}

在这里,对于从 webClient 请求返回的每个值(只有一个),我们将结果投影到您的 Data 类中,而不是执行可观察流之外的转换。

我对你的方法做了一些小修改。我不太喜欢这样带有副作用的代码(传递集合来贡献似乎是错误的向量),但我会允许它。除此之外,我认为这应该效果很好。

关于.net - Observable 和 Webclient 获取 csv,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9308744/

相关文章:

C# WebClient,仅支持HTML3.2

C# WebClient DownloadString 返回乱码

c# - 如何将二维数组传递给存储过程?

c# - DateTime.ToString ("T") 和 DateTime.ToString ("G") 中的错误?

php - 处理 CSV 文件中各个单元格中的换行符

python - 如何从具有词频的CSV文件生成词云

javascript - 使用 JavaScript 将 HTML 表导出到 CSV 时保留前导零

c# - 需要身份验证的 Silverlight 和 ATOM 源

c# - QueryOver:从子查询中选择列

c# - 在商业应用中使用 Fluent NHibernate