2012-12-04 13 views
7

çalışmadığı çünkü devlet bağlanması bloke WCF vekil kesme yoktur. "Problem" i göstermek için yazdığım bir test uygulamasına sahibim. (Bu, WCF'nin çalıştığı ve bu konuda yapabileceğim hiçbir şey olmadığı fikrine açığım.)nasıl uzaktan servis ben arama adil bir miktar yaptık ve bir çözüm veya buna bir cevap bulmak mümkün olmamıştır

Test uygulamam, Visual Studio tarafından oluşturulan bir proxy'ye sahip basit bir WCF hizmeti ve istemcisidir. Vekil olan bir uzak makinede işaret ettim, ancak hizmeti çalıştırmıyordum. Bu nokta önemli. Uzak makine hiç çalışmıyorsa, WCF çağrısı hemen başarısız olur.

istemci uygulaması, istemci vekil sınıfının bir örneğini oluşturur Yeni Görevi başladı ve daha sonra diğer ucunda servis olmadığından engeller hizmet arabirimde bir çağrı yapmak için çalışır. Arka plan Görevi 5 saniye boyunca uyur ve ardından proxy'yi kapatır. Vekili kapatırken diğer iş parçacığı hemen hata bekliyordum, ama değil. İlk aramayı yaptıktan yaklaşık 20 saniye sonra, daha sonra arızalanır. İşte

müvekkilim kodudur:

using System; 
using System.ServiceModel; 
using System.Threading; 
using System.Threading.Tasks; 
using TestConsoleClient.MyTestServiceReference; 

namespace TestConsoleClient 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     MyTestServiceClient client = new MyTestServiceClient(); 

     // Start new thread and wait a little bit before trying to close connection. 
     Task.Factory.StartNew(() => 
     { 
      LogMessage("Sleeping for 5 seconds ..."); 
      Thread.Sleep(5000); 
      if (client == null) 
      { 
       LogMessage("Woke up! Proxy was closed before waking up."); 
       return; 
      } 

      LogMessage("Woke up! Attempting to abort connection."); 
      LogMessage(string.Format("Channel state before Close: {0}", 
       ((ICommunicationObject)client).State)); 

      client.Close(); 
      ((IDisposable)client).Dispose(); 
      client.Abort(); 

      // Channel state is Closed, as expected, but blocked thread does not wake up? 
      LogMessage(string.Format("Channel state after Abort: {0}", 
       ((ICommunicationObject)client).State)); 

      client = null; 
     }); 

     // Start connecting. 
     LogMessage("Starting connection ..."); 

     try 
     { 
      LogMessage("Calling MyTestService.DoWork()"); 
      client.DoWork(); // Timeout is 60 seconds. State is "Connecting" 
     } 
     catch (Exception ex) 
     { 
      LogMessage(string.Format("Exception caught: {0}", ex.Message)); 
      if (client != null) 
      { 
       client.Abort(); 
       ((IDisposable) client).Dispose(); 
       client = null; 
      } 
     } 
     finally 
     { 
      if (client != null) 
      { 
       client.Close(); 
       client = null; 
      } 
     } 

     LogMessage("Press Enter to exit ..."); 

     Console.ReadLine(); 
    } 

    private static void LogMessage(string msg) 
    { 
     Console.WriteLine("{0}: [{1}] {2}", 
          DateTime.Now.ToString("hh:mm:ss tt"), Thread.CurrentThread.ManagedThreadId, msg); 
    } 
} 
} 

Ve işte benim programın çıktısı şöyledir:

01:48:31 PM: [9] Starting connection ... 
01:48:31 PM: [9] Calling MyTestService.DoWork() 
01:48:31 PM: [10] Sleeping for 5 seconds ... 
01:48:36 PM: [10] Woke up! Attempting to abort connection. 
01:48:36 PM: [10] Channel state before Close: Opening 
01:48:36 PM: [10] Channel state after Abort: Closed 
01:48:54 PM: [9] Exception caught: Could not connect to net.tcp://th-niconevm:80 
80/MyTestService. The connection attempt lasted for a time span of 00:00:22.0573 
009. TCP error code 10060: A connection attempt failed because the connected par 
ty did not properly respond after a period of time, or established connection fa 
iled because connected host has failed to respond 10.10.10.10:8080. 
01:48:54 PM: [9] Press Enter to exit ... 

Ne kullanıcı izin başarmak çalışıyorum bu yüzden olabilir bağlamak kesme Gerekirse ayarlamalar yapın ve tekrar deneyin. Çıkışta görebildiğiniz gibi, kanal "Açılış" durumundan sonra "Kapalı" durumuna geçer, ancak servis çağrısı zaman aşımına uğrayana kadar engellenir. Kesinlikle etrafta çalışabilirim, ama bunu kesmenin bir yolu olmalı. Ardından kod çok daha basit hale gelir, sen asenkron operasyonlarla proxy sınıfı oluşturmak

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
<system.serviceModel> 
    <bindings> 
     <netTcpBinding> 
      <binding name="NetTcpBinding_IMyTestService" closeTimeout="00:01:00" 
       openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" 
       transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" 
       hostNameComparisonMode="StrongWildcard" listenBacklog="10" 
       maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10" 
       maxReceivedMessageSize="65536"> 
       <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" 
        maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
       <reliableSession ordered="true" inactivityTimeout="00:10:00" 
        enabled="false" /> 
       <security mode="Transport"> 
        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> 
        <message clientCredentialType="Windows" /> 
       </security> 
      </binding> 
     </netTcpBinding> 
    </bindings> 
    <client> 
     <endpoint address="net.tcp://remotehost:8080/MyTestService" binding="netTcpBinding" 
      bindingConfiguration="NetTcpBinding_IMyTestService" contract="MyTestServiceReference.IMyTestService" 
      name="NetTcpBinding_IMyTestService"> 
      <identity> 
       <userPrincipalName value="remotehost\ClientUser" /> 
      </identity> 
     </endpoint> 
    </client> 
</system.serviceModel> 
</configuration> 
+0

Ciltleme yapılandırması nedir? Espeially receTimeout? 'Böylece teorik olarak bunu; (TimeSpan.FromSeconds (2))' client.Close: Bir Görev In Action istemci asıl soruya app.config ... – sll

+0

bir 'Yakın()' çağrı için açık zaman aşımı geçen denemek max 2 saniye –

+0

ekleme – sll

cevap

0

Daha kilometre alabilirsiniz:

İşte istemci app.config bu. o, yardımcı zaman uyumsuz desen üzerinde okumak olabilir gibi

// Asynchronously call DoWork 
MyTestServiceClient client = new MyTestServiceClient(); 
IAsyncResult iar = client.BeginDoWork(null, null); 

// Sleep, dance, do the shopping, whatever 
Thread.Sleep(5000); 

bool requestCompletedInFiveSeconds = iar.IsCompleted; 

// When you're ready, remember to call EndDoWork to tidy up 
client.EndDoWork(iar); 
client.Close(); 

o geliyorsa. This MSKB, şaşırtıcı derecede yararlıdır ve eşzamansız kod yazmanın çeşitli yollarını gösterir.

Senin sorunun may aslında devam eden bir WCF işlemi iptal hiçbir yolu olmadığını olmak; Bunun için kendi iptal mekanizmanızı yazmanız gerekir. Örneğin, bir isteği devam aslında (yani .: DoWork yürütme iptal edilmesi gerekmektedir) ya da bazı ağ veya diğer makine gecikme soygunu ise eğer söylemek mümkün olmayacaktır.

+1

bilmemize izin verdiysem çok hızlı bir şekilde fark ettim ki, eğer uygulama orijinal olarak async ile yazılsaydı, bu bir sorun olmazdı. Ne yazık ki, eşzamanlı WCF çağrılarına (çift yönlü TCP) dayalı önemli bir kod tabanına bakıyorum ve bunu kullanan çerçeveyi ve sunum katmanını değiştirmek için önemli miktarda iş olacaktır. Bu beni üzüyor, ama ben buyum. Orijinal sorumu ortaya çıkarmak için, bağlantının zaman aşımından önce kesilmesinin gerçekten bir yolu yok mu? Yerel yuva katmanında, bir soket tutamacının kapatılması, engellenen çağrıları kesintiye uğratır. Yani, mümkün olduğunu biliyorum. –

+0

Ne yazık ki sizin için böyle düşünmüyorum. Kontrolde olduğunuza göre DoWork'u eşzamansız olarak çağırmanız gerekir. Kodunuzu çevirin, böylece istemciyi izlemek için bir görev oluşturmak yerine, 'DoWork' adını vermek için bir görev oluşturursunuz? Daha sonra bu görevi izleyebilirsiniz ve eğer çok uzun sürerse onu öldürürsünüz. – batwad

İlgili konular