Запуск объекта Object Event, находящегося в потоке, созданном пользовательским интерфейсом (ASPX) - PullRequest
0 голосов
/ 01 марта 2019

Я собираюсь отбросить это для большинства страниц, на которые я смотрел, кажется, не близко к тому, что я имею, или я не понимаю, что они говорят и надеются на ясный пример /понимание.Я опытный программист, но не умею работать с потоками в пользовательском интерфейсе и обработкой событий с пользовательскими объектами.

Я создал библиотеку 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 , и оно не запускается / не выполняется, когда объект в потоке пытается отправить сообщение, поэтому пока таймер работает и поток работает, сообщений об обновлении нет.появляются, потому что событие не выполняется.Я читал и смотрел на такие вещи, как диспетчеры, слушатели, фоновые работники, делегаты, пока у меня не кружилась голова, и я не могу понять, как подключить локальный поток, чтобы сообщить потоку пользовательского интерфейса, что объект в локальном потоке запущен.

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

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