1

XSL を使用して XML ファイルを変換し、出力を印刷しようとしています。ただし、次のメッセージが表示されます。別のスレッドがこのオブジェクトを所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません。

ファイルをチェックする間隔を設定するために、OnStart にタイマーを追加しました。

            if (findPrinter() > 0)
            {
                System.Timers.Timer printNetterCheck = new System.Timers.Timer();
                printNetterCheck.Elapsed += new ElapsedEventHandler(OnTimedEvent);

                printNetterCheck.Interval = 30000;
                printNetterCheck.Enabled = true;
            }

OnTimedEvent:

    private void OnTimedEvent(object source, ElapsedEventArgs e)
    {            
        getFiles();
    }

使用可能なファイルがある場合は、print を呼び出します。

            foreach (string file in files)
            {
                try
                {
                    StringWriter xslTransformResult = new StringWriter();
                    XslCompiledTransform xslt = new XslCompiledTransform();
                    xslt.Load(xslPath);
                    xslt.Transform(file, null, xslTransformResult);

                    if (print(xslTransformResult) == 1)
                    {
                              //do some things

印刷機能:

    private int print(StringWriter transformedXML)
    {
        //assume OK
        int rc = 1;

        try
        {
            StringReader printNetterStreamReader = new StringReader(transformedXML.ToString());
            PrintSystemJobInfo printNetterJob = printer.AddJob("PrintNetterPrint");

            Stream printNetterStream = printNetterJob.JobStream;


            Byte[] printNetterByteBuffer = UnicodeEncoding.Unicode.GetBytes(printNetterStreamReader.ReadToEnd());

            printNetterStream.Write(printNetterByteBuffer, 0, printNetterByteBuffer.Length);
            printNetterStream.Close();
        }
        catch (Exception e)
        {
            //return fail
            rc = -1;
            eventLog.WriteEntry("Error printing: " + e.Message, EventLogEntryType.Error);
        }

        return rc;

    }

print を呼び出すと、スレッドエラーが発生します。Dispatchers などに関するいくつかの情報が見つかりましたが、サービスを使用している場合は利用できません。

4

2 に答える 2

1

確認してくださいPrintQueue.AddJob

このメソッドは、アプリケーションが 1 つのアパートメント ( STA) で実行されている必要がある COM 呼び出しを行います。これを修正する最も簡単な方法は、アプリケーションを強制的にシングル スレッドで実行するように追加することSTAThreadAttributeです。Mainアプリケーションでマルチスレッドが必要な場合は、必要な配管を実装しPrintQueueて、STA Thread.

// Create a factory to hold your printer configuration
// So that it can be retrieved on demand
// You might need to move the findPrinter() logic
public class PrintQueueFactory
{
    private static PrintQueue _instance = new PrinterQueue(/* Details */);

    public static PrintQueue PrintQueue { get { return _instance; } }
}

private int print(StringWriter transformedXML)
{
    //assume OK
    int rc = 1;

    try
    {
        var printer = PrintQueueFactory.PrintQueue;
        var staThread = new Thread(() => Print(printer, transformedXML.ToString()));
        staThread.SetApartmentState(ApartmentState.STA);
        staThread.Start();
        staThread.Join();
    }
    catch (Exception e)
    {
        //return fail
        rc = -1;
        eventLog.WriteEntry("Error printing: " + e.Message, EventLogEntryType.Error);
    }

    return rc;

}

private static void Print(PrintQueue printer, string lines)
{
    using(var printNetterJob = printer.AddJob("PrintNetterPrint"))
    using(var printNetterStreamReader = new StringReader(lines))
    using(var printNetterStream = printNetterJob.JobStream)
    {
        Byte[] printNetterByteBuffer = UnicodeEncoding.Unicode.GetBytes(printNetterStreamReader.ReadToEnd());
        printNetterStream.Write(printNetterByteBuffer, 0, printNetterByteBuffer.Length);
    }
}
于 2013-04-22T12:44:48.487 に答える
0

おそらく、Timer コントロールを使用しているため、マルチスレッドに関連しているため、Timer.Elapsed イベント ハンドラーで Invoke が必要 (InvokeRequired) かどうかを確認する必要があります。

その場合は、この関数を呼び出すデリゲートを作成して、適切なスレッドで実行できるようにする必要があります。

この呼び出しが必要な質問を確認してください

于 2013-04-22T11:46:17.287 に答える