2010-09-22 3 views
2

Я пытаюсь интегрировать некоторый новый код, который я написал для программного взаимодействия с Exchange 2010 через Remote Powershell в существующее приложение WinForms. Мой код работает в изолированном тестовом приложении, но когда я запускаю код в контексте моего приложения, вызов в Runspace.Open() блокируется в течение очень долгого времени - за минусом OpenTimeout значение 60 секунд, которое я указываю в примере WSManConnectionInfo. Для меня это говорит о том, что в нашем коде приложения есть что-то, что создает проблему, но у меня возникают проблемы с сужением возможных причин. Приложение многопоточное и использует как BackgroundThreadWorker, так и ThreadPool; на самом деле мой код работает через ThreadPool в приложении. Но я уже пробовал имитировать это в своей тестовой жгуте, и код отлично работает, когда вызывается как обратный вызов из ThreadPool.Почему мой вызов Runspace.Open() не возвращается?

Вот код (с обработкой ошибок удаляются и постоянные определения поставить рядом):

const string EXCHANGE_PS_URI_FORMAT = "http://{0}/PowerShell/"; 
string uriString = string.Format(EXCHANGE_PS_URI_FORMAT, HostName); 
Uri connectionUri = new Uri(uriString); 

PSCredential creds = new PSCredential(username, securePwd); 

const string EXCHANGE_PS_SCHEMA_URL = 
    "http://schemas.microsoft.com/powershell/Microsoft.Exchange"; 
WSManConnectionInfo connectionInfo = 
    new WSManConnectionInfo(connectionUri, EXCHANGE_PS_SCHEMA_URL, creds); 

const int DEFAULT_OPEN_TIMEOUT = 1 * 60 * 1000; // 1 minute 
connectionInfo.OpenTimeout = DEFAULT_OPEN_TIMEOUT; 
const int DEFAULT_OPERATION_TIMEOUT = 4 * 60 * 1000; // 4 minutes 
connectionInfo.OperationTimeout = DEFAULT_OPERATION_TIMEOUT; 

using (Runspace rs = RunspaceFactory.CreateRunspace(connectionInfo)) 
{ 
    // BUGBUG: WHY IS THIS FAILING TO RETURN? 
    rs.Open(); // <-- HANGS HERE 

    ICollection<PSObject> newReqResults = null; 
    PipelineReader<object> newReqErrors = null; 
    try 
    { 
     using (Pipeline pipeline = rs.CreatePipeline()) 
     { 
      // cmd instance is already instantiated with cmdlet info, params, etc. 
      pipeline.Commands.Add(cmd); 

      //Invoke the command and return the results and errors 
      newReqResults = pipeline.Invoke(); 
      newReqErrors = pipeline.Error; 
     } 
    } 

    // Code to parse results and/or errors... 

Стек вызовов, когда код висит на Runspace.Open(), кажется, показывает, что внутренний код .NET застрял на ожидания звоните, но я не понимаю, как это сделать. Как я уже говорил ранее, этот код отлично работает в моем тестовом приложении, даже если он вызван как обратный вызов ThreadPool, поэтому мне интересно, что может быть в нашем главном коде приложения, который может вызвать это (контекст синхронизации или идентификатор потока или что-то еще?) Любая помощь будет принята с благодарностью. Пожалуйста, дайте мне знать, если я пренебрег включением некоторых релевантных сведений, и я с удовольствием включу их. Благодаря!

[In a sleep, wait, or join] 
mscorlib.dll!System.Threading.WaitHandle.WaitOne(long timeout, bool exitContext) + 0x2f bytes 
mscorlib.dll!System.Threading.WaitHandle.WaitOne(int millisecondsTimeout, bool exitContext) + 0x25 bytes  
mscorlib.dll!System.Threading.WaitHandle.WaitOne() + 0xd bytes 
System.Management.Automation.dll!System.Management.Automation.Runspaces.AsyncResult.EndInvoke() + 0x14 bytes  
System.Management.Automation.dll!System.Management.Automation.Runspaces.Internal.RunspacePoolInternal.EndOpen(System.IAsyncResult asyncResult) + 0xb2 bytes 
System.Management.Automation.dll!System.Management.Automation.Runspaces.Internal.RemoteRunspacePoolInternal.Open() + 0x1a bytes 
System.Management.Automation.dll!System.Management.Automation.Runspaces.RunspacePool.Open() + 0x48 bytes  
System.Management.Automation.dll!System.Management.Automation.RemoteRunspace.Open() + 0x73 bytes  

ответ

2

Возможно ли, что при запуске программы в threadpool, чтобы поток был заблокирован? Возможно, вы действительно хотите здесь позвонить OpenAsync, а не Open.

+0

Это определенно вероятность того, что рабочий поток заблокирован из-за чего-то в том, как работает многопоточность. Я по-прежнему предпочитаю, чтобы код моего приложения был синхронным, но у меня может не быть выбора с надвигающимися сроками. Я посмотрю, что я могу прототип вокруг OpenAsync, но я действительно хотел бы понять причину здесь - в частности, что такое вызов ThreadPool.Open(), стоящий в ожидании? – Matt

+0

ОК, я думаю, я понимаю, что происходит сейчас. Вы правы, что поток заблокирован; это потому, что в нашем приложении есть код для уменьшения максимального количества потоков ThreadPool, и это приводит к тупиковой операции Runspace.Open(). Если я увеличу максимальное количество потоков ThreadPool, вызов Runspace.Open() вернется, и мой код будет продолжать, как ожидалось. Несмотря на то, что мне не нужно было использовать OpenAsync(), я отмечаю это как ответ, потому что причина была правильной - поток был заблокирован. – Matt

Смежные вопросы