none
[ASP.NET]CSV作成&ダウンロード処理を、別スレッドで実行 RRS feed

  • 質問

  • はじめまして。
    ASP.NET, C#の初心者です。よろしくお願い致します。

    Webアプリケーションを作っています。
    CSVファイルの作成処理を、別スレッドを作成して実行したいと考えています。(処理が重いため)

    そして、なんとかCSVファイルを別スレッド利用で出力することはできたのですが、、、
    CSV形式データの下(同ファイル内)に、呼び出し元のHTMLソースも入った状態で出力されてしまいます。

    純粋にCSV形式のデータのみを出力するには、どのようにしたらよいのでしょうか?
    ご教授願います。


    <<出力ファイルの内容>>

    "項目1","項目2","項目3", ~

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transiti ~
    <html>


    <<出力処理の内容>>

    ①呼出元ページから、ResponseとDataTableを渡して別スレッドを作成し、スタートする。

    <呼出元に記述>
    ThreadClass tc = new ThreadClass(DataTable, Response);
    Thread thread = new Thread(new ThreadStart(tc.CsvExec);
    thread.Start();

    <スレッドクラスに記述>
    private DataTable datatable;
    private HttpResponse response;

    public ThreadClass(DataTable dt, HttpResponse res){
    datatable = dt;
    response = res;
    }


    ②呼出元から受け取ったResponseに、各種設定を行う。

    response.ContentType = "application/octet-stream";
    response.AppendHeader("Content-Disposition", "attachment; filename=searchdb.csv");
    response.ContentEncoding = System.Text.Encoding.GetEncoding("Shift_JIS");
    response.Clear();
    response.BufferOutput = false;


    ③受け取ったDataTableの内容をCSV編集し、バッファに書き込む。

    String[] TableDataStr = new string[datatable.Column.Count];
    StringBuilder buffer = new StringBuilder();
    for (int i = 0; i < datatable.Rows.Count; i++)
    {
    for (int j = 0; j < datatable.Columns.Count; j++)
    {
    TableDataStr[j] = datatable.Rows[ i ].ItemArray[ j ].ToString();
    }

    buffer.Remove(0, buffer.Length);
    buffer.Append("\"");
    buffer.Append(String.Join("\",\"", TableDataStr));
    buffer.Append("\"");
    buffer.Append("\r\n");

    response.Write(buffer.ToString());
    response.Flush();
    }


    ④終了させる。

    Response.End();


    以上、よろしくお願い致します。
    2007年6月15日 8:07

すべての返信

  •  おれんぢ さんからの引用

    Webアプリケーションを作っています。
    CSVファイルの作成処理を、別スレッドを作成して実行したいと考えています。(処理が重いため)

     

    余計なお世話かもしれませんが、Web アプリケーションで自分勝手にスレッドを起こすのは危ういです。

    特に重要な処理を実行させるのであれば避けるべきです。

     

    参考:

    http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?mode=viewtopic&topic=38563&forum=7&start=13

     

    2007年6月15日 16:53
    モデレータ
  • 別のスレッドでResponse.Endを実行しても、元のスレッドのページ処理は終了できないですし、いろんな意味で整合性の取れない状態になると思います。

     

    CSVファイルの作成処理を、別スレッドを作成して実行したいと考えています。(処理が重いため)

    とのことですが、具体的に何の処理が重いのでしょうか?

    別スレッドにしたからといって軽くなるようには思えません。むしろ、Threadを直接作成するような処理をしていると、余計に負荷がかかる可能性があります。

    2007年6月16日 1:28
  • 渋木宏明(ひどり)様
    なちゃ様

    ご回答ありがとうございます。

    >
    余計なお世話かもしれませんが、Web アプリケーションで自分勝手にスレッドを起こすのは危ういです。

    特に重要な処理を実行させるのであれば避けるべきです。


    ご指摘ありがとうございます。

    Webアプリケーションで別スレッドを作成することの危険性を認識してませんでした。

    元々の、同一スレッドでの処理で実行する方向で検討したいと思います。

    CSVの作成処理自体は、重要な処理ではないです。(あくまで付加機能)



    >
    具体的に何の処理が重いのでしょうか?

    別スレッドにしたからといって軽くなるようには思えません。むしろ、Threadを直接作成するような処理を

    していると、余計に負荷がかかる可能性があります。


    恐らく、対象データ量が多い為、DataTableの内容をCSV形式に変換→バッファ書き込みの一連を

    繰り返しに時間が掛かるものと思います。

    別スレッド化によって、余計な負荷がかかることもあるのですね。。。



    今回、、、
    データベース内の各テーブルデータを参照するインターフェースを作っています。
    操作としては、
    ①対象のテーブルを選択
    ②テーブルのフィールドから、必要なフィールドを選択
     (①,②の作業を繰り返し、複数のテーブルのフィールドを同時に選択することも可能)
    ③検索実行
    ④検索結果表示
    ⑤必要に応じて、ボタン押下により検索結果をCSV出力

    そして、対象とするテーブルの内、1テーブルが問題で、、、
    本来1300項目程度あるデータをテーブル(SQL Server)に収めるため、1レコード100項目として
    仮の項目名を付けて、分割して格納しています。(1レコード(毎分) → 13レコード(毎分)に分割)

    上記②の際には、本来の項目名を選択して検索実行するようにし、
    上記④の際には、当然、本来の項目名にて②で選択した項目のみを表示しなければなりません。

    そして現在、テストを行っているのですが、
    全項目(1300項目程度)を選択して
    2時間分までのデータを対象とした場合は、
    時間はかかるものの、何とか結果表示およびCSVダウンロードまではできます。

    しかし、全項目選択して3時間分を対象とすると、
    何とか結果表示はされるんですが、CSVダウンロードができなくなります。(DNSエラー)
    それ以上の時間分を対象とすると、結果表示すらできなくなります。(同じく、DNSエラー)
    (DNSエラー=何かのタイムアウト??)

    (当然、ユーザには使用しないようには伝えますが・・・)最低限、時間はかかってもエラーが
    出ない状態には持っていきたかったので、パフォーマンスが上がれば出ないのでは?と思い、
    パフォーマンスを上げる策を探していました。
    それで、パフォーマンス向上?タイムアウト回避?を目的に、別スレッド化を検討していました。

    2007年6月18日 2:42