У меня есть программа, которая создает два файла PDF при нажатии кнопки. Он использует взаимодействие Microsoft office в WinForms, и создание файла происходит следующим образом:
- Пользователь работает над чем-то в программе
- Нажимает кнопку
- Программа создает слово файл на основе шаблона, в котором есть закладки
- Записывает как в закладки, так и в свою таблицу
- Сохраняет его как pdf
- Закрывает активные документы
- Закрывает приложение Word
- Закрывает дочернюю форму и переключается на другую
* приложение Word не отображается для пользователя
Само по себе работает нормально , но затем для завершения двух файлов требуется 8 секунд, поэтому я попытался использовать многопоточность, чтобы пользователю не приходилось ждать, и он мог работать над другими делами или снова перейти к шагу 1.
Однако при этом возникают различные ошибки; COM, RP C и др. c. даже в соединениях с базой данных, и я думаю, причина в том, что, поскольку есть два отдельных потока, которые работают и используют одни и те же ресурсы, в какой-то момент другой может закрыть ресурсы, которые другой поток использует / собирается использовать Поэтому я попытался использовать join (), чтобы другой поток мог сначала завершить sh свою работу, закрыть соответствующие ресурсы, а затем перейти к следующему.
Это работает нормально, ЕСЛИ пользователь не нажмите кнопку, чтобы создать еще один файл сразу за другим (в сценарии, когда пользователь завершает первый шаг быстрее, чем ожидалось)
join()
достаточно для обработки ошибок, а также для работы с создание файлов в фоновом режиме, однако я хочу иметь дело со сценарием, когда создание файла выполняется сразу после другого, потому что в этом сценарии ios кажется, что процесс является линейным из-за потоков, ожидающих друг друга, помимо этого создает узкие места, в которых потоки теперь находятся в очереди и блокируют основной поток, который заставляет пользователя ждать 12 секунд или более.
Я хочу знать / уточнить следующее:
- Могу ли я создать эти два файла, которые использует
interop
использовать разные ресурсы, чтобы не создавать ошибок? - Могу ли я использовать или есть альтернатива
join()
, в которой он не блокирует поток пользовательского интерфейса или основной поток? Чтобы файл, создающий потоки, просто выстраивался в фоновом режиме (все еще ждет друг друга, чтобы завершить sh), не заставляя пользователя ждать. - Я неправильно использовал join () или потоки, которые в итоге съедают больше time?
Вот мой код;
Процедура и переменные publi c в модуле для создания документов:
Public tsThread As Thread
Public psThread As Thread
Sub SaveDoc(docType,someArgs)
Dim wordApp = New Word.Application
Dim templateBookmarks As Word.Bookmarks
Dim templateName As String
Dim template As New Word.Document
wordApp = CreateObject("Word.Application")
Select Case docType
Case "Type1"
templateName = "SampleType.docx"
template = wordApp.Documents.Add(templatePath & templateName)
templateBookmarks = template.Bookmarks
templateBookmarks.Item("bookmarkInWord").Range.Text = "Foo"
template.Tables(1).Cell(msWordRow, 1).Range.Text = "Value in cell 1"
Case "Type2"
‘Same thing, just different values and template
Case "Type3"
End select
template.SaveAs2(savePath & saveName, Word.WdSaveFormat.wdFormatPDF)
wordApp.ActiveDocument.Close(Word.WdSaveOptions.wdDoNotSaveChanges)
wordApp.Quit()
End Sub
Процедура в дочернем форма при нажатии кнопки:
If Not IsNothing(tsThread) Then
If tsThread.IsAlive Then
tsThread.Join()
End If
End If
If Not IsNothing(psThread) Then
If psThread.IsAlive Then
psThread.Join()
End If
End If
tsThread = New Thread(Sub() SaveDoc(docType1,someArgs))
tsThread.Start()
If Not IsNothing(tsThread) Then
If tsThread.IsAlive Then
tsThread.Join()
End If
End If
psThread = New Thread(Sub() SaveDoc(docType2,someArgs))
psThread.Start()
If records = maxRecords Then
If psThread.IsAlive or tsThread.isAlive Then
tsThread.Join()
psThread.Join()
Dim fooThread = New Thread(Sub() SaveDoc(docType3,someArgs))
fooThread.Start()
End If
End If
SwitchForm("Child Form for Step 1")
End Sub
Ошибки, т.е. без использования join()
, обычно встречаются в следующих частях кода:
wordApp.ActiveDocument.Close(Word.WdSaveOptions.wdDoNotSaveChanges)
или в
wordApp.Quit()
Или в закладках
templateBookmarks.Item("bookmarkInWord").Range.Text = "Foo"
Или иногда где угодно внутри одного из кейсов в разное время или в процедурах подключения к базе данных .
Я все еще относительно новичок в многопоточности, а также в Ms Interop, поэтому я обращаюсь за помощью, если у меня есть какие-либо неправильные представления. Код находится на VB, но я тоже могу понять C#. Любая помощь / руководство приветствуется. Спасибо!