2016-12-05 6 views
0

に私は次のようにリスナーを開始:は、ActiveXは、WebSocketのサーバーの開発にAsyncCallback

private void StartAccept() 
{ 
    _listener.BeginAcceptTcpClient(new AsyncCallback(HandleAsyncConnection), null); 
} 

、複数の接続を受け入れることができるように非ブロックを有するため。

応答コールバック関数の一つが選択されたデフォルトのプリンタにHTMLページを印刷する必要があります

私はAsyncCallback内からのWebBrowserオブジェクトを作成しようとするので失敗している
WebBrowser webBrowser = new WebBrowser(); 
webBrowser.DocumentText = "<html><body><p>I am HTML text!</p><body></html>"; 
webBrowser.Print(); 

ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment. 

ここでWebBrowserオブジェクトを作成するにはどうすればよいですか?次の答えに

+1

の可能性のある重複した[シングルスレッドアパートメント - ActiveXコントロールをインスタンス化することはできません](http://stackoverflow.com/questions/1418466/single-threaded-apartment-cannot-instantiate-activex-control) –

+1

または、専用のSTAスレッドと印刷用のキューを考慮すると、インスタンス化は1回だけ必要です。 –

+0

ヒント..ありがとう..私はいくつかのリンクをたどった後、私は完璧に動作するこのソリューションで終わった:http://stackoverflow.com/questions/416314/print-html-document-from-windows-service-in-c-鮮明でない印刷ダイアログ –

答えて

0

ありがとう:

Print html document from Windows Service in C# without print dialog

私は印刷作業を取得することができました:

//-------------------------------------------------------------------------- 
// 
// Copyright (c) Microsoft Corporation. All rights reserved. 
// 
// File: StaTaskScheduler.cs 
// 
//-------------------------------------------------------------------------- 

using System.Collections.Concurrent; 
using System.Collections.Generic; 
using System.Linq; 

namespace System.Threading.Tasks.Schedulers 
{ 
    /// <summary>Provides a scheduler that uses STA threads.</summary> 
    public sealed class StaTaskScheduler : TaskScheduler, IDisposable 
    { 
     /// <summary>Stores the queued tasks to be executed by our pool of STA threads.</summary> 
     private BlockingCollection<Task> _tasks; 
     /// <summary>The STA threads used by the scheduler.</summary> 
     private readonly List<Thread> _threads; 

     /// <summary>Initializes a new instance of the StaTaskScheduler class with the specified concurrency level.</summary> 
     /// <param name="numberOfThreads">The number of threads that should be created and used by this scheduler.</param> 
     public StaTaskScheduler(int numberOfThreads) 
     { 
      // Validate arguments 
      if (numberOfThreads < 1) throw new ArgumentOutOfRangeException("concurrencyLevel"); 

      // Initialize the tasks collection 
      _tasks = new BlockingCollection<Task>(); 

      // Create the threads to be used by this scheduler 
      _threads = Enumerable.Range(0, numberOfThreads).Select(i => 
      { 
       var thread = new Thread(() => 
       { 
        // Continually get the next task and try to execute it. 
        // This will continue until the scheduler is disposed and no more tasks remain. 
        foreach (var t in _tasks.GetConsumingEnumerable()) 
        { 
         TryExecuteTask(t); 
        } 
       }); 
       thread.IsBackground = true; 
       thread.SetApartmentState(ApartmentState.STA); 
       return thread; 
      }).ToList(); 

      // Start all of the threads 
      _threads.ForEach(t => t.Start()); 
     } 

     /// <summary>Queues a Task to be executed by this scheduler.</summary> 
     /// <param name="task">The task to be executed.</param> 
     protected override void QueueTask(Task task) 
     { 
      // Push it into the blocking collection of tasks 
      _tasks.Add(task); 
     } 

     /// <summary>Provides a list of the scheduled tasks for the debugger to consume.</summary> 
     /// <returns>An enumerable of all tasks currently scheduled.</returns> 
     protected override IEnumerable<Task> GetScheduledTasks() 
     { 
      // Serialize the contents of the blocking collection of tasks for the debugger 
      return _tasks.ToArray(); 
     } 

     /// <summary>Determines whether a Task may be inlined.</summary> 
     /// <param name="task">The task to be executed.</param> 
     /// <param name="taskWasPreviouslyQueued">Whether the task was previously queued.</param> 
     /// <returns>true if the task was successfully inlined; otherwise, false.</returns> 
     protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) 
     { 
      // Try to inline if the current thread is STA 
      return 
       Thread.CurrentThread.GetApartmentState() == ApartmentState.STA && 
       TryExecuteTask(task); 
     } 

     /// <summary>Gets the maximum concurrency level supported by this scheduler.</summary> 
     public override int MaximumConcurrencyLevel 
     { 
      get { return _threads.Count; } 
     } 

     /// <summary> 
     /// Cleans up the scheduler by indicating that no more tasks will be queued. 
     /// This method blocks until all threads successfully shutdown. 
     /// </summary> 
     public void Dispose() 
     { 
      if (_tasks != null) 
      { 
       // Indicate that no new tasks will be coming in 
       _tasks.CompleteAdding(); 

       // Wait for all threads to finish processing tasks 
       foreach (var thread in _threads) thread.Join(); 

       // Cleanup 
       _tasks.Dispose(); 
       _tasks = null; 
      } 
     } 
    } 
} 

StaTaskScheduler Sta = new StaTaskScheduler(1); 

public void PrintHtml(string htmlPath) 
{ 
    Task.Factory.StartNew(() => PrintOnStaThread(htmlPath), CancellationToken.None, TaskCreationOptions.None, Sta).Wait(); 
} 

void PrintOnStaThread(string htmlText) 
{ 
    const short PRINT_WAITFORCOMPLETION = 2; 
    const int OLECMDID_PRINT = 6; 
    const int OLECMDEXECOPT_DONTPROMPTUSER = 2; 
    using (var browser = new WebBrowser()) 
    { 
     browser.DocumentText = htmlText; 
     while (browser.ReadyState != WebBrowserReadyState.Complete) 
      Application.DoEvents(); 

     dynamic ie = browser.ActiveXInstance; 
     ie.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, PRINT_WAITFORCOMPLETION); 
    } 
} 

StaTaskSchedulerは、上記のスレッドから来ています

今私は自分のAsyncCallbackから印刷できます呼び出し元:

PrintHtml("<html><body><h1>I AM A html text</h1></body></hmtl>"); 
関連する問題