나는 돋보이는 편지 병합을 한 다음 PDF로 파일 변환하는 중입니다 ... .Net 4.5를 기반으로하면 스레딩을 할 수있는 몇 가지 방법이 있습니다. thread safe queue를 사용하는 것은 재미있을 것 같지만 (Plan A), 잠재적 인 문제를 볼 수 있습니다. 어떻게 생각해? 나는 그것을 짧게하려고 노력할 것이지만, 필요한 것을 넣을 것입니다.ConcurrentQueue를이 방법이나 개별 스레드로 사용해야합니까?
이 작업은 PDF 변환보다 데이터베이스 처리를 수행하는 데 더 많은 시간이 걸릴 것이라는 가정하에 작동합니다.
두 경우 모두 각 파일에 대한 데이터베이스 처리는 자체 스레드/작업으로 수행되지만 PDF 변환은 많은 단일 스레드/작업 (계획 B)에서 수행되거나 단일 실행 스레드에서 수행 될 수 있습니다 (계획 A). 그것은 제가 궁금해하는 PDF 변환입니다. 그것은 모두 try/catch 문에 있지만 스레드가 실패하거나 모두 실패하지 않아야합니다 (계획 A). 그게 좋은 생각이라고 생각하니? 모든 제안을 부탁드립니다.
/* A class to process a file: */
public class c_FileToConvert
{
public string InFileName { get; set; }
public int FileProcessingState { get; set; }
public string ErrorMessage { get; set; }
public List<string> listData = null;
c_FileToConvert(string inFileName)
{
InFileName = inFileName;
FileProcessingState = 0;
ErrorMessage = ""; // yah, yah, yah - String.Empty
listData = new List<string>();
}
public void doDbProcessing()
{
// get the data from database and put strings in this.listData
DAL.getDataForFile(this.InFileName, this.ErrorMessage); // static function
if(this.ErrorMessage != "")
this.FileProcessingState = -1; //fatal error
else // Open file and append strings to it
{
foreach(string s in this.listData}
...
FileProcessingState = 1; // enum DB_WORK_COMPLETE ...
}
}
public void doPDFProcessing()
{
PDFConverter cPDFConverter = new PDFConverter();
cPDFConverter.convertToPDF(InFileName, InFileName + ".PDF");
FileProcessingState = 2; // enum PDF_WORK_COMPLETE ...
}
}
/*** These only for Plan A ***/
public ConcurrentQueue<c_FileToConvert> ConncurrentQueueFiles = new ConcurrentQueue<c_FileToConvert>();
public bool bProcessPDFs;
public void doProcessing() // This is the main thread of the Windows Service
{
List<c_FileToConvert> listcFileToConvert = new List<c_FileToConvert>();
/*** Only for Plan A ***/
bProcessPDFs = true;
Task task1 = new Task(new Action(startProcessingPDFs)); // Start it and forget it
task1.Start();
while(1 == 1)
{
List<string> listFileNamesToProcess = new List<string>();
DAL.getFileNamesToProcessFromDb(listFileNamesToProcess);
foreach(string s in listFileNamesToProcess)
{
c_FileToConvert cFileToConvert = new c_FileToConvert(s);
listcFileToConvert.Add(cFileToConvert);
}
foreach(c_FileToConvert c in listcFileToConvert)
if(c.FileProcessingState == 0)
Thread t = new Thread(new ParameterizedThreadStart(c.doDbProcessing));
/** This is Plan A - throw it on single long running PDF processing thread **/
foreach(c_FileToConvert c in listcFileToConvert)
if(c.FileProcessingState == 1)
ConncurrentQueueFiles.Enqueue(c);
/*** This is Plan B - traditional thread for each file conversion ***/
foreach(c_FileToConvert c in listcFileToConvert)
if(c.FileProcessingState == 1)
Thread t = new Thread(new ParameterizedThreadStart(c.doPDFProcessing));
int iCount = 0;
for(int iCount = 0; iCount < c_FileToConvert.Count; iCount++;)
{
if((c.FileProcessingState == -1) || (c.FileProcessingState == 2))
{
DAL.updateProcessingState(c.FileProcessingState)
listcFileToConvert.RemoveAt(iCount);
}
}
sleep(1000);
}
}
public void startProcessingPDFs() /*** Only for Plan A ***/
{
while (bProcessPDFs == true)
{
if (ConncurrentQueueFiles.IsEmpty == false)
{
try
{
c_FileToConvert cFileToConvert = null;
if (ConncurrentQueueFiles.TryDequeue(out cFileToConvert) == true)
cFileToConvert.doPDFProcessing();
}
catch(Exception e)
{
cFileToConvert.FileProcessingState = -1;
cFileToConvert.ErrorMessage = e.message;
}
}
}
}
계획안은 좋은 해결책 인 것처럼 보이지만 작업이 어떻게 든 실패하면 어떻게됩니까? 예, 개별 스레드로 PDF 변환을 수행 할 수 있지만 데이터베이스 처리를 위해 PDF 변환을 예약하려고합니다.
이것은 내가 할 수있는 가장 간단한 코드로 텍스트 편집기에서 작성되었으므로 뭔가있을 수 있지만 생각이 바뀌 었다고 생각합니다.
PDF 변환 CPU 또는 IO가 제한되어 있습니까? – Richard
CPU에 바인딩되어야합니다. 문서 당 약 2 초가 걸립니다. 내 가정은 내 병 목이 데이터베이스에있는 것입니다. – Miguelito
리소스가 성능을 제한하는 위치를 알아야합니다. 모든 CPU 리소스 (코어)를 사용하는 데 효과가있는 동시성 접근 방식은 IO에서 제대로 작동하지 않습니다 (예 : 스레드간에 동일한 총 IO를 분산 시키면 각 변환에 더 오래 걸리고 총 처리량은 거의 변하지 않습니다) . – Richard