强制循环包含异步任务以维护序列

时间:2012-12-05 00:21:35

标签: c# loops asynchronous printing backgroundworker

有些东西告诉我这可能是一个愚蠢的问题,事实上我已经从错误的方向解决了我的问题,但是这里有。

我有一些代码循环遍历文件夹中的所有文档 - 每个文件夹中这些文档的字母顺序很重要,这一重要性也反映在文档的打印顺序中。这是一个简化版本:

var wordApp = new Microsoft.Office.Interop.Word.Application();

foreach (var file in Directory.EnumerateFiles(folder))
      {
          fileCounter++;

          // Print file, referencing a previously instantiated word application object
          wordApp.Documents.Open(...)
          wordApp.PrintOut(...)
          wordApp.ActiveDocument.Close(...)
      }

看起来(我可能错了)PrintOut代码是异步的,应用程序有时会进入文档无序打印的情况。这已得到确认,因为如果我单步执行或拨打足够长的Sleep()电话,则所有文件的顺序都是正确的。

如何阻止下一个打印任务在上一个打印任务完成之前启动?

我最初认为我可以使用lock(someObject){},直到我记得它们只对防止多个线程访问相同的代码块有用。这都是在同一个线程上。

我可以在Microsoft.Office.Interop.Word.Application对象上加入一些事件:DocumentOpenDocumentBeforeCloseDocumentBeforePrint

我认为这可能实际上是打印队列无法准确区分在同一秒内添加的大量文档的问题。这不是问题,可以吗?

作为旁注,此循环位于从BackgroundWorker对象的DoWork事件调用的代码中。我正在使用它来阻止UI阻止并反馈流程的进度。

2 个答案:

答案 0 :(得分:1)

您的事件处理方法似乎很好。您可以向DocumentBeforeClose事件添加处理程序,而不是使用循环,您可以在其中获取要打印的下一个文件,将其发送到Word,然后继续。像这样:

List<...> m_files = Directory.EnumerateFiles(folder);
wordApp.DocumentBeforeClose += ProcessNextDocument;

...

void ProcessNextDocument(...)
{
    File file = null;
    lock(m_files)
    {
        if (m_files.Count > 0)
        {
            file = m_files[m_files.Count - 1];
            m_files.RemoveAt(m_files.Count - 1);
        }
        else
        {
            // Done!
        }
    }

    if (file != null)
    {
        PrintDocument(file);
    }
}

void PrintDocument(File file)
{
    wordApp.Document.Open(...);
    wordApp.Document.PrintOut(...);
    wordApp.ActiveDocument.Close(...);
}

答案 1 :(得分:0)

Application.PrintOut的第一个参数指定打印是否应在后台进行。通过将其设置为false,它将同步工作。