Как я могу использовать context.Response.OutputStream в потоке - PullRequest
0 голосов
/ 03 мая 2019

Идея состоит в том, чтобы следить за ходом процесса извлечения данных из базы данных в другие CSV-файлы, которые на последнем шаге будут скопированы в один zip-файл, используя zip.Save(context.Response.OutputStream) пакета Ionic.Zip, файл будет загружен пользователем.

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

Моя форма ASPX

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="TestThread.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server"> 
</asp:ScriptManager>
<asp:Timer runat="server" ID="Tikawa" Interval="1000" Enabled="false" ontick="Tikawa_Tick" />
<br />

    <div class="newsletter-subscribe">
    <div class="container">
        <div class="intro">

                <div class="form-group" align="center">       
                                <asp:Button ID="processing" runat="server" Text="Run"   class="button" OnClick="processing_Click"/>
                        </div>

                <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
                    <Triggers>
                        <asp:AsyncPostBackTrigger ControlID="Tikawa" EventName="Tick" />
                    </Triggers>
                    <ContentTemplate>
                        <br />
                        <asp:TextBox ID="TextBox1" runat="server" Height="250px" TextMode="MultiLine" 
                            Width="800px"></asp:TextBox>
                    </ContentTemplate>
                </asp:UpdatePanel>

        </div>
    </div>
</div>

</div>
</form>
</body>
</html>

Мой код C #:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Text;
using Ionic.Zip;
using System.Threading;

namespace TestThread
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected static string content;
        protected static bool inProcess = false;
        protected static bool processComplete = false;

        protected static string processCompleteMsg = "Finished Processing All Records.";

        protected void Page_Load(object sender, EventArgs e)
        {
        }

        protected void processing_Click(object sender, EventArgs e)
        {
            processing.Enabled = false;
            Tikawa.Enabled = true;

            HttpContext ctx = HttpContext.Current;
            Work worker = new Work();

            Thread t = new Thread(new ThreadStart(() =>
                                  {
                                      HttpContext.Current = ctx;
                                      worker.DoWork();
                                  }));
            t.Start();
            //t.Join();
        }

        protected void Tikawa_Tick(object sender, EventArgs e)
        {
            if (inProcess)
                 TextBox1.Text = content;

            int msgLen = processCompleteMsg.Length;

            if (processComplete && TextBox1.Text.Substring(TextBox1.Text.Length - processCompleteMsg.Length) == processCompleteMsg) //has final message been set?
            {
                inProcess = false;
                Tikawa.Enabled = false;
                processing.Enabled = true;
            }
        }

        class Work
        {
            public static string ConvertDataTableToString(DataTable dt)
            {
                StringBuilder sb = new StringBuilder();

                for (int k = 0; k < dt.Columns.Count; k++)
                {
                    sb.Append(dt.Columns[k].ColumnName + ',');
                }

                sb.Append("\r\n");

                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    for (int k = 0; k < dt.Columns.Count; k++)
                    {
                        sb.Append(dt.Rows[i][k].ToString().Replace(",", ";") + ';');
                    }

                    sb.Append("\r\n");
                }

                return sb.ToString();
            }

            public class Files
            {
                public string TableName { get; set; }
                public byte[] Bytes { get; set; }
            }

            public void DoWork()
            {
                HttpContext context = HttpContext.Current;
                inProcess = true;
                Thread.Sleep(1000);

                DataSet ds = new DataSet();

                content += "Start creation of the 1st Table " + System.Environment.NewLine ;

                DataTable dt1 = new DataTable();
                dt1.TableName = "Table1";
                dt1.Columns.AddRange(new DataColumn[3] {
                           new DataColumn("Id", typeof(int)),
                           new DataColumn("Name", typeof(string)),
                           new DataColumn("Country",typeof(string)) });

                dt1.Rows.Add(1, "John Hammond", "United States");
                dt1.Rows.Add(2, "Mudassar Khan", "India");
                dt1.Rows.Add(3, "Suzanne Mathews", "France");
                dt1.Rows.Add(4, "Robert Schidner", "Russia");

                Thread.Sleep(2000);
                content += "End creation of the 1st Table " + System.Environment.NewLine;

                content += "Start creation of the 2nd Table " + System.Environment.NewLine;

                DataTable dt2 = new DataTable();
                dt2.TableName = "Table2";
                dt2.Columns.AddRange(new DataColumn[3] {
                       new DataColumn("Id", typeof(int)),
                       new DataColumn("Name", typeof(string)),
                       new DataColumn("Country",typeof(string)) });

                dt2.Rows.Add(1, "Maria", "Austria");
                dt2.Rows.Add(2, "Thomas Hardy", "Ireland");
                dt2.Rows.Add(3, "Laurence Lebihan", "USA");
                dt2.Rows.Add(4, "Victoria Ashworth", "UK");

                Thread.Sleep(2000);
                content += "End creation of the 2nd Table " +   System.Environment.NewLine;

                Thread.Sleep(2000);
                content += "Start CSV Export" + System.Environment.NewLine;

                ds.Tables.Add(dt1);
                ds.Tables.Add(dt2);

                List<Files> txtData = new List<Files>();

                foreach (DataTable dt in ds.Tables)
                {
                    byte[] bytes = Encoding.ASCII.GetBytes(ConvertDataTableToString(dt));
                    txtData.Add(new Files() { TableName = dt.TableName,  Bytes = bytes });
                }

                Thread.Sleep(2000);
                content += "End CSV Export" + System.Environment.NewLine;

                Thread.Sleep(2000);
                content += "Start ZIP Preparation" + System.Environment.NewLine;

                using (ZipFile zip = new ZipFile())
                {
                    zip.AlternateEncodingUsage = ZipOption.AsNecessary;

                    foreach (Files txtData in txtDatas)
                    {
                        zip.AddEntry(txtData.TableName + ".csv", txtData.Bytes);
                    }

                    Thread.Sleep(2000);
                    content += "End ZIP Preparation" + System.Environment.NewLine;

                    Thread.Sleep(2000);
                    content += "Start ZIP Downloading" + System.Environment.NewLine;

                    context.Response.Clear();
                    context.Response.BufferOutput = false;
                    string zipName = String.Format("Bingo_{0}.zip", DateTime.Now.ToString("mmss"));
                    context.Response.ContentType = "application/zip";
                    context.Response.AddHeader("content-disposition",   "attachment; filename=" + zipName);

                    zip.Save(context.Response.OutputStream);
                    context.Response.End();

                    Thread.Sleep(2000);
                    content += "End ZIP Downloading" + System.Environment.NewLine;
                }

                processComplete = true;
                content += processCompleteMsg;
            }
        }
    }
}

Мой код бросается в строку:

context.Response.AddHeader("content-disposition", "attachment; filename=" + zipName);

но если я добавлю t.join () после начала потока, заархивированный файл будет сгенерирован и загружен, но форма по-прежнему будет зависать без какой-либо информации о прогрессе, пока не будет выполнена вся обработка.

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