Идея состоит в том, чтобы следить за ходом процесса извлечения данных из базы данных в другие 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 () после начала потока, заархивированный файл будет сгенерирован и загружен, но форма по-прежнему будет зависать без какой-либо информации о прогрессе, пока не будет выполнена вся обработка.