Я собираюсь отбросить это для большинства страниц, на которые я смотрел, кажется, не близко к тому, что я имею, или я не понимаю, что они говорят и надеются на ясный пример /понимание.Я опытный программист, но не умею работать с потоками в пользовательском интерфейсе и обработкой событий с пользовательскими объектами.
Я создал библиотеку DLL с одним событием
public event EventHandler<StdMessageArgs> onSendMessage;
Позже, в классеЕсли я хочу отправить сообщение обратно в программу, которая создала объект, я использую этот метод:
private void log(string msg, char errType)
{
onSendMessage(this, new StdMessageArgs(msg, errType));
}
Я создал консольное приложение, которое успешно использует это.Я создаю объект и добавляю событие с помощью следующих операторов:
// set up the class object and it's event
VDKItemImportToCM.VDKItemImporter itemImport = new VDKItemImportToCM.VDKItemImporter(PSWebconnectString, x3v6connectString, tableList);
itemImport.onSendMessage += itemImport_OnMsg;
и позже я могу отображать и регистрировать сообщения, используя это событие:
public static void itemImport_OnMsg(object sender, VDKItemImportToCM.VDKItemImporter.StdMessageArgs e)
{
switch (e.ErrorType)
{
case 'i':
log.Info(e.Msg);
break;
case 'e':
log.Error(e.Msg);
break;
case 'f':
log.Fatal(e.Msg);
Environment.Exit(-900);
break;
}
}
Это прекрасно работает для моего консольного приложения,но я хочу использовать ту же библиотеку DLL для веб-формы ASP, чтобы сотрудники могли выполнять ту же задачу, что и консольная программа.Мне пришлось решить две проблемы.Первым было, как обновить текстовое поле в режиме реального времени, и благодаря Stackoverflow я нашел решение.Это источник страницы, где для обновления текстового поля используется таймер:
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<asp:Timer runat="server" ID="Timer1" Interval="1000" Enabled="false" ontick="Timer1_Tick" />
<table style="width: 800px">
<tr>
<td align="center" colspan="2" height="40px">
<asp:Label ID="Label1" runat="server" Text="Van Dyke Item Import to CM" class="heading1" Font-Bold="False" Font-Names="Verdana" ForeColor="Blue" Font-Size="Medium"></asp:Label>
</td>
</tr>
<tr>
<td colspan="2" style="padding-bottom: 30px; margin-bottom: 30px">
<asp:Label ID="lblImportMessages" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td style="width: 187px">
<asp:Label ID="Label2" runat="server" Text="Select Excel Import File:"></asp:Label>
</td>
<td>
<asp:FileUpload ID="fulExcelFile" runat="server" Width="315px" />
</td>
</tr>
<tr>
<td colspan="2" height="45px">
<asp:Button ID="btnImportItems" runat="server" OnClick="btnImportItems_Click" Text="Import Items" />
</td>
</tr>
<tr>
<td colspan="2">Import Progress</td>
</tr>
<tr>
<td colspan="2">
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:TextBox ID="txtDisplayProgress" runat="server" Height="400px" TextMode="MultiLine" Width="100%"></asp:TextBox>
</ContentTemplate>
</asp:UpdatePanel>
</td>
</tr>
</table>
Они показали, что в примере, который я нашел, это делается для запуска основной рабочей нагрузки в потоке, когдакнопка нажата, вот мой обратный код при нажатии кнопки:
protected void btnImportItems_Click(object sender, EventArgs e)
{
string filename = Path.GetFileName(fulExcelFile.FileName);
// check for valid file extension
if (fulExcelFile.HasFile)
{
String fileExtension = System.IO.Path.GetExtension(fulExcelFile.FileName).ToLower();
String[] allowedExtensions = { ".xlsx" };
if (fileExtension != ".xlsx")
{
lblImportMessages.Text = "The file name is incorrect (Excel .xlsx)";
return;
}
}
btnImportItems.Enabled = false;
Timer1.Enabled = true;
Thread workerThread = new Thread(new ParameterizedThreadStart(processClientExcel));
workerThread.Start(fulExcelFile);
// processClientExcel(fulExcelFile);
}
Вы можете видеть, что он запускает метод с именем processClientExcel, который имеет в себе те же операторы объекта / события из консоли
VDKItemImporter itemImport = new VDKItemImporter(PSWeb, x3v6, tableList);
itemImport.onSendMessage += itemImport_OnMsg;
и в бэкэнд-код для формы я добавил событие из объекта itemImport:
protected void itemImport_OnMsg(object sender, VDKItemImporter.StdMessageArgs e)
{
string errorType = "";
switch (e.ErrorType)
{
case 'i':
errorType = "Info: ";
break;
case 'e':
errorType = "Error: ";
break;
case 'f':
errorType = "Fatal: ";
break;
}
content += errorType + e.Msg + "\r\n";
//txtDisplayProgress.Text += errorType + e.Msg + "\r\n";
}
Для ведения хозяйства эти переменные добавляются в код формы для управления обработкой таймера / потока:
protected static string content;
protected static bool inProcess = false;
protected static bool processComplete = false;
Я решил основную первую проблему с наличием текстового поля и показывает ход обновления с помощью приложения updatePanel / timer / thread.Однако ключом к этому является событие объекта itemImport_OnMsg , и оно не запускается / не выполняется, когда объект в потоке пытается отправить сообщение, поэтому пока таймер работает и поток работает, сообщений об обновлении нет.появляются, потому что событие не выполняется.Я читал и смотрел на такие вещи, как диспетчеры, слушатели, фоновые работники, делегаты, пока у меня не кружилась голова, и я не могу понять, как подключить локальный поток, чтобы сообщить потоку пользовательского интерфейса, что объект в локальном потоке запущен.
Какой код мне не хватает или сколько мне нужно переписать библиотеку классов, чтобы она работала между двумя различными средами (консоль / веб-форма).