ASP.NET SignalR Hubs API 가이드 - .NET 클라이언트(SignalR 1.x)

작성자 : Patrick Fletcher, Tom Dykstra

경고

이 설명서는 최신 버전의 SignalR용이 아닙니다. ASP.NET Core SignalR을 살펴보세요.

이 문서에서는 WinRT(Windows 스토어), WPF, Silverlight 및 콘솔 애플리케이션과 같은 .NET 클라이언트에서 SignalR 버전 2용 Hubs API를 사용하는 방법을 소개합니다.

SignalR Hubs API를 사용하면 서버에서 연결된 클라이언트로, 클라이언트에서 서버로 RPC(원격 프로시저 호출)를 수행할 수 있습니다. 서버 코드에서 클라이언트에서 호출할 수 있는 메서드를 정의하고 클라이언트에서 실행되는 메서드를 호출합니다. 클라이언트 코드에서는 서버에서 호출할 수 있는 메서드를 정의하고 서버에서 실행되는 메서드를 호출합니다. SignalR은 모든 클라이언트-서버 배관을 처리합니다.

또한 SignalR은 영구 연결이라는 하위 수준 API를 제공합니다. SignalR, Hubs 및 영구 연결에 대한 소개 또는 전체 SignalR 애플리케이션을 빌드하는 방법을 보여 주는 자습서는 SignalR - 시작 참조하세요.

개요

이 문서는 다음 섹션으로 구성됩니다.

샘플 .NET 클라이언트 프로젝트는 다음 리소스를 참조하세요.

서버 또는 JavaScript 클라이언트를 프로그래밍하는 방법에 대한 설명서는 다음 리소스를 참조하세요.

API 참조 topics 대한 링크는 .NET 4.5 버전의 API에 대한 링크입니다. .NET 4를 사용하는 경우 API topics .NET 4 버전을 참조하세요.

클라이언트 설치

Microsoft.AspNet.SignalR.Client NuGet 패키지(Microsoft.AspNet.SignalR 패키지 아님)를 설치합니다. 이 패키지는 .NET 4 및 .NET 4.5 모두에 대해 WinRT, Silverlight, WPF, 콘솔 애플리케이션 및 Windows Phone 클라이언트를 지원합니다.

클라이언트에 있는 SignalR 버전이 서버에 있는 버전과 다른 경우 SignalR은 종종 차이점에 적응할 수 있습니다. 예를 들어 SignalR 버전 2.0이 릴리스되고 서버에 설치하는 경우 서버는 1.1.x가 설치된 클라이언트와 2.0이 설치된 클라이언트를 지원합니다. 서버의 버전과 클라이언트의 버전 간의 차이가 너무 크면 클라이언트가 연결을 설정하려고 할 때 SignalR에서 예외를 throw합니다 InvalidOperationException . 오류 메시지는 "You are using a version of the client that isn't compatible with the server. Client version X.X, server version X.X"입니다.

연결을 설정하는 방법

연결을 설정하려면 개체를 만들고 프록시를 HubConnection 만들어야 합니다. 연결을 설정하려면 개체에서 메서드를 StartHubConnection 호출합니다.

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start();

참고

JavaScript 클라이언트의 경우 연결을 설정하기 위해 메서드를 호출 Start 하기 전에 하나 이상의 이벤트 처리기를 등록해야 합니다. .NET 클라이언트에는 필요하지 않습니다. JavaScript 클라이언트의 경우 생성된 프록시 코드는 서버에 있는 모든 Hubs에 대한 프록시를 자동으로 만들고 처리기를 등록하면 클라이언트에서 사용할 허브를 나타내는 방법이 됩니다. 그러나 .NET 클라이언트의 경우 허브 프록시를 수동으로 만들므로 SignalR은 프록시를 만드는 허브를 사용한다고 가정합니다.

샘플 코드는 기본 "/signalr" URL을 사용하여 SignalR 서비스에 연결합니다. 다른 기본 URL을 지정하는 방법에 대한 자세한 내용은 ASP.NET SignalR Hubs API 가이드 - 서버 - /signalr URL을 참조하세요.

메서드는 Start 비동기적으로 실행됩니다. 연결이 설정될 때까지 후속 코드 줄이 실행되지 않도록 하려면 ASP.NET 4.5 비동기 메서드 또는 .Wait() 동기 메서드에서 를 사용합니다await. WinRT 클라이언트에서는 를 사용하지 .Wait() 마세요.

await connection.Start();
connection.Start().Wait();

HubConnection 클래스는 스레드로부터 안전합니다.

Silverlight 클라이언트에서 도메인 간 연결

Silverlight 클라이언트에서 도메인 간 연결을 사용하도록 설정하는 방법에 대한 자세한 내용은 도메인 경계를 넘어 서비스를 사용할 수 있도록 만들기를 참조하세요.

연결을 구성하는 방법

연결을 설정하기 전에 다음 옵션 중 원하는 옵션을 지정할 수 있습니다.

  • 동시 연결 제한.
  • 쿼리 문자열 매개 변수입니다.
  • 전송 메서드입니다.
  • HTTP 헤더.
  • 클라이언트 인증서.

WPF 클라이언트에서 최대 동시 연결 수를 설정하는 방법

WPF 클라이언트에서는 기본값인 2에서 최대 동시 연결 수를 늘려야 할 수 있습니다. 권장 값은 10입니다.

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
ServicePointManager.DefaultConnectionLimit = 10;
await hubConnection.Start();

자세한 내용은 ServicePointManager.DefaultConnectionLimit를 참조하세요.

쿼리 문자열 매개 변수를 지정하는 방법

클라이언트가 연결할 때 서버에 데이터를 보내려는 경우 연결 개체에 쿼리 문자열 매개 변수를 추가할 수 있습니다. 다음 예제에서는 클라이언트 코드에서 쿼리 문자열 매개 변수를 설정하는 방법을 보여줍니다.

var querystringData = new Dictionary<string, string>();
querystringData.Add("contosochatversion", "1.0");
var connection = new HubConnection("http://contoso.com/", querystringData);

다음 예제에서는 서버 코드에서 쿼리 문자열 매개 변수를 읽는 방법을 보여줍니다.

public class StockTickerHub : Hub
{
    public override Task OnConnected()
    {
        var version = Context.QueryString["contosochatversion"];
        if (version != "1.0")
        {
            Clients.Caller.notifyWrongVersion();
        }
        return base.OnConnected();
    }
}

전송 방법을 지정하는 방법

연결 프로세스의 일부로 SignalR 클라이언트는 일반적으로 서버와 협상하여 서버와 클라이언트 모두에서 지원하는 최상의 전송을 결정합니다. 사용하려는 전송을 이미 알고 있는 경우 이 협상 프로세스를 무시할 수 있습니다. 전송 메서드를 지정하려면 전송 개체를 Start 메서드에 전달합니다. 다음 예제에서는 클라이언트 코드에서 전송 메서드를 지정하는 방법을 보여줍니다.

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start(new LongPollingTransport());

Microsoft.AspNet.SignalR.Client.Transports 네임스페이스에는 전송을 지정하는 데 사용할 수 있는 다음 클래스가 포함되어 있습니다.

  • LongPollingTransport
  • ServerSentEventsTransport
  • WebSocketTransport (서버와 클라이언트 모두 .NET 4.5를 사용하는 경우에만 사용 가능)
  • AutoTransport (클라이언트와 서버 모두에서 지원하는 최상의 전송을 자동으로 선택합니다. 기본 전송입니다. 메서드에 Start 전달하면 아무 것도 전달하지 않는 것과 같은 효과가 있습니다.)

ForeverFrame 전송은 브라우저에서만 사용되므로 이 목록에 포함되지 않습니다.

서버 코드에서 전송 메서드를 검사 방법에 대한 자세한 내용은 ASP.NET SignalR Hubs API 가이드 - 서버 - Context 속성에서 클라이언트에 대한 정보를 가져오는 방법을 참조하세요. 전송 및 대체에 대한 자세한 내용은 SignalR 소개 - 전송 및 대체를 참조하세요.

HTTP 헤더를 지정하는 방법

HTTP 헤더를 설정하려면 연결 개체의 Headers 속성을 사용합니다. 다음 예제에서는 HTTP 헤더를 추가하는 방법을 보여줍니다.

hubConnection = new hubConnection("http://www.contoso.com/");
connection.Headers.Add("headername", "headervalue");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await connection.Start();

클라이언트 인증서를 지정하는 방법

클라이언트 인증서를 추가하려면 연결 개체에서 AddClientCertificate 메서드를 사용합니다.

hubConnection = new hubConnection("http://www.contoso.com/");
hubConnection.AddClientCertificate(X509Certificate.CreateFromCertFile("MyCert.cer"));
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await connection.Start();

허브 프록시를 만드는 방법

허브가 서버에서 호출할 수 있는 클라이언트의 메서드를 정의하고 서버의 허브에서 메서드를 호출하려면 연결 개체를 호출 CreateHubProxy 하여 허브에 대한 프록시를 만듭니다. 에 전달하는 문자열은 허브 클래스의 이름 또는 서버에서 CreateHubProxy 사용된 경우 특성으로 HubName 지정된 이름입니다. 이름 일치 시 대/소문자는 구분하지 않습니다.

서버의 허브 클래스

public class StockTickerHub : Hub

허브 클래스에 대한 클라이언트 프록시 만들기

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start();

특성을 사용하여 Hub 클래스를 데코레이트하는 HubName 경우 해당 이름을 사용합니다.

서버의 허브 클래스

[HubName("stockTicker")]
public class StockTickerHub : Hub

허브 클래스에 대한 클라이언트 프록시 만들기

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("stockTicker");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start();

프록시 개체는 스레드로부터 안전합니다. 실제로 동일한 를 사용하여 여러 번 호출 HubConnection.CreateHubProxy 하면 동일한 hubName캐시된 IHubProxy 개체가 표시됩니다.

서버에서 호출할 수 있는 클라이언트에서 메서드를 정의하는 방법

서버에서 호출할 수 있는 메서드를 정의하려면 프록시의 On 메서드를 사용하여 이벤트 처리기를 등록합니다.

메서드 이름 일치는 대/소문자를 구분하지 않습니다. 예를 들어 Clients.All.UpdateStockPrice 서버에서 클라이언트에서 , updatestockprice또는 UpdateStockPrice 를 실행updateStockPrice합니다.

클라이언트 플랫폼에 따라 UI를 업데이트하는 메서드 코드를 작성하는 방법에 대한 요구 사항이 다릅니다. 표시된 예제는 WinRT(Windows 스토어 .NET) 클라이언트에 대한 것입니다. WPF, Silverlight 및 콘솔 애플리케이션 예제는 이 항목의 뒷부분에 있는 별도의 섹션에 제공됩니다.

매개 변수가 없는 메서드

처리 중인 메서드에 매개 변수가 없는 경우 메서드의 제네릭이 아닌 오버로드를 On 사용합니다.

매개 변수 없이 클라이언트 메서드를 호출하는 서버 코드

public class StockTickerHub : Hub
{
    public void NotifyAllClients()
    {
         Clients.All.Notify();
    }
}

매개 변수 없이 서버에서 호출되는 메서드에 대한 WinRT 클라이언트 코드(이 항목의 뒷부분에 나오는 WPF 및 Silverlight 예제 참조)

var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHub.On("notify", () =>
    // Context is a reference to SynchronizationContext.Current
    Context.Post(delegate
    {
        textBox.Text += "Notified!\n";
    }, null)
);
await hubConnection.Start();

매개 변수가 있는 메서드, 매개 변수 형식 지정

처리 중인 메서드에 매개 변수가 있는 경우 매개 변수의 형식을 메서드의 On 제네릭 형식으로 지정합니다. 최대 8개의 매개 변수를 지정할 수 있도록 하는 메서드의 On 일반 오버로드가 있습니다(Windows Phone 7의 경우 4). 다음 예제에서는 하나의 매개 변수가 메서드로 UpdateStockPrice 전송됩니다.

매개 변수를 사용하여 클라이언트 메서드를 호출하는 서버 코드

public void BroadcastStockPrice(Stock stock)
{
    context.Clients.Others.UpdateStockPrice(stock);
}

매개 변수에 사용되는 Stock 클래스

public class Stock
{
    public string Symbol { get; set; }
    public decimal Price { get; set; }
}

매개 변수가 있는 서버에서 호출된 메서드에 대한 WinRT 클라이언트 코드(이 항목의 뒷부분에 있는 WPF 및 Silverlight 예제 참조)

stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    // Context is a reference to SynchronizationContext.Current
    Context.Post(delegate
    {
        textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
    }, null)
);

매개 변수가 있는 메서드, 매개 변수에 대한 동적 개체 지정

매개 변수를 메서드의 제네릭 형식으로 지정하는 대신 매개 변수를 On 동적 개체로 지정할 수 있습니다.

매개 변수를 사용하여 클라이언트 메서드를 호출하는 서버 코드

public void BroadcastStockPrice(Stock stock)
{
    context.Clients.Others.UpdateStockPrice(stock);
}

매개 변수에 사용되는 Stock 클래스

public class Stock
{
    public string Symbol { get; set; }
    public decimal Price { get; set; }
}

매개 변수에 동적 개체를 사용하여 매개 변수가 있는 서버에서 호출되는 메서드에 대한 WinRT 클라이언트 코드(이 항목의 뒷부분에 있는 WPF 및 Silverlight 예제 참조).

stockTickerHubProxy.On("UpdateStockPrice", stock => 
    // Context is a reference to SynchronizationContext.Current
    Context.Post(delegate
    {
        textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
    }, null)
);

처리기를 제거하는 방법

처리기를 제거하려면 해당 메서드를 호출합니다 Dispose .

서버에서 호출된 메서드에 대한 클라이언트 코드

var updateStockPriceHandler = stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    Context.Post(delegate
    {
        textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
    }, null)
);

처리기를 제거하는 클라이언트 코드

updateStockPriceHandler.Dispose();

클라이언트에서 서버 메서드를 호출하는 방법

서버에서 메서드를 호출하려면 허브 프록시에서 Invoke 메서드를 사용합니다.

서버 메서드에 반환 값이 없는 경우 메서드의 제네릭이 아닌 오버로드를 Invoke 사용합니다.

반환 값이 없는 메서드에 대한 서버 코드

public class StockTickerHub : Hub
{
    public void JoinGroup(string groupName)
    {
        Groups.Add(Context.ConnectionId, groupName); 
    }
}

반환 값이 없는 메서드를 호출하는 클라이언트 코드

stockTickerHubProxy.Invoke("JoinGroup", hubConnection.ConnectionID, "SignalRChatRoom");

서버 메서드에 반환 값이 있는 경우 반환 형식을 메서드의 Invoke 제네릭 형식으로 지정합니다.

반환 값이 있고 복합 형식 매개 변수를 사용하는 메서드에 대한 서버 코드

public IEnumerable<Stock> AddStock(Stock stock)
{
    _stockTicker.AddStock(stock);
    return _stockTicker.GetAllStocks();
}

매개 변수 및 반환 값에 사용되는 Stock 클래스

public class Stock
{
    public string Symbol { get; set; }
    public decimal Price { get; set; }
}

반환 값이 있고 ASP.NET 4.5 비동기 메서드에서 복합 형식 매개 변수를 사용하는 메서드를 호출하는 클라이언트 코드

var stocks = await stockTickerHub.Invoke<IEnumerable<Stock>>("AddStock", new Stock() { Symbol = "MSFT" });
foreach (Stock stock in stocks)
{
    textBox.Text += string.Format("Symbol: {0} price: {1}\n", stock.Symbol, stock.Price);
}

반환 값이 있고 동기 메서드에서 복합 형식 매개 변수를 사용하는 메서드를 호출하는 클라이언트 코드

var stocks = stockTickerHub.Invoke<IEnumerable<Stock>>("AddStock", new Stock() { Symbol = "MSFT" }).Result;
foreach (Stock stock in stocks)
{
    textBox.Text += string.Format("Symbol: {0} price: {1}\n", stock.Symbol, stock.Price);
}

메서드는 Invoke 비동기적으로 실행되고 개체를 Task 반환합니다. 또는 .Wait()을 지정 await 하지 않으면 호출하는 메서드가 실행을 완료하기 전에 다음 코드 줄이 실행됩니다.

연결 수명 이벤트를 처리하는 방법

SignalR은 처리할 수 있는 다음과 같은 연결 수명 이벤트를 제공합니다.

  • Received: 연결에서 데이터를 수신할 때 발생합니다. 받은 데이터를 제공합니다.
  • ConnectionSlow: 클라이언트가 느리거나 자주 연결을 삭제하는 것을 감지할 때 발생합니다.
  • Reconnecting: 기본 전송이 다시 연결되기 시작할 때 발생합니다.
  • Reconnected: 기본 전송이 다시 연결되었을 때 발생합니다.
  • StateChanged: 연결 상태가 변경될 때 발생합니다. 이전 상태와 새 상태를 제공합니다. 연결 상태 값에 대한 자세한 내용은 ConnectionState 열거형을 참조하세요.
  • Closed: 연결이 끊어지면 발생합니다.

예를 들어 치명적이지는 않지만 연결 속도가 느리거나 연결이 자주 삭제되는 등의 일시적인 연결 문제를 일으키는 오류에 대한 경고 메시지를 표시하려는 경우 이벤트를 처리합니다 ConnectionSlow .

hubConnection.ConnectionSlow += () => Console.WriteLine("Connection problems.");

자세한 내용은 SignalR에서 연결 수명 이벤트 이해 및 처리를 참조하세요.

오류를 처리하는 방법

서버에서 자세한 오류 메시지를 명시적으로 사용하도록 설정하지 않으면 오류 발생 후 SignalR이 반환하는 예외 개체에 오류에 대한 최소한의 정보가 포함됩니다. 예를 들어 에 대한 호출 newContosoChatMessage 이 실패하면 오류 개체의 오류 메시지에 "There was an error invoking Hub method 'contosoChatHub.newContosoChatMessage'."가 포함되어 있습니다. 프로덕션 환경에서 클라이언트에 자세한 오류 메시지를 보내는 것은 보안상의 이유로 권장되지 않지만 문제 해결을 위해 자세한 오류 메시지를 사용하도록 설정하려면 서버에서 다음 코드를 사용합니다.

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
RouteTable.Routes.MapHubs(hubConfiguration);

SignalR에서 발생하는 오류를 처리하려면 연결 개체에서 Error 이벤트에 대한 처리기를 추가할 수 있습니다.

hubConnection.Error += ex => Console.WriteLine("SignalR error: {0}", ex.Message);

메서드 호출의 오류를 처리하려면 try-catch 블록에 코드를 래핑합니다.

try
{
    IEnumerable<Stock> stocks = await stockTickerHub.Invoke<IEnumerable<Stock>>("GetAllStocks");
    foreach (Stock stock in stocks)
    {
        Console.WriteLine("Symbol: {0} price: {1}", stock.Symbol, stock.Price);
    }
}
catch (Exception ex)
{
    Console.WriteLine("Error invoking GetAllStocks: {0}", ex.Message);
}

클라이언트 쪽 로깅을 사용하도록 설정하는 방법

클라이언트 쪽 로깅을 사용하도록 설정하려면 연결 개체에서 TraceLevelTraceWriter 속성을 설정합니다.

var hubConnection = new HubConnection("http://www.contoso.com/");
hubConnection.TraceLevel = TraceLevels.All;
hubConnection.TraceWriter = Console.Out;
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price));
await hubConnection.Start();

서버에서 호출할 수 있는 클라이언트 메서드에 대한 WPF, Silverlight 및 콘솔 애플리케이션 코드 샘플

서버에서 호출할 수 있는 클라이언트 메서드를 정의하기 위해 이전에 표시된 코드 샘플은 WinRT 클라이언트에 적용됩니다. 다음 샘플에서는 WPF, Silverlight 및 콘솔 애플리케이션 클라이언트에 해당하는 코드를 보여 줍니다.

매개 변수가 없는 메서드

매개 변수 없이 서버에서 호출된 메서드에 대한 WPF 클라이언트 코드

stockTickerHub.On<Stock>("notify", () =>
    Dispatcher.InvokeAsync(() =>
        {
            SignalRTextBlock.Text += string.Format("Notified!");
        })
);

매개 변수 없이 서버에서 호출된 메서드에 대한 Silverlight 클라이언트 코드

stockTickerHub.On<Stock>("notify", () =>
    // Context is a reference to SynchronizationContext.Current
    Context.Post(delegate
    {
        textBox.Text += "Notified!";
    }, null)
);

매개 변수 없이 서버에서 호출된 메서드에 대한 콘솔 애플리케이션 클라이언트 코드

stockTickerHubProxyProxy.On("Notify", () => Console.WriteLine("Notified!"));

매개 변수가 있는 메서드, 매개 변수 형식 지정

매개 변수가 있는 서버에서 호출된 메서드에 대한 WPF 클라이언트 코드

stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    Dispatcher.InvokeAsync(() =>
        {
            textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
        })
);

매개 변수가 있는 서버에서 호출된 메서드에 대한 Silverlight 클라이언트 코드

stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    // Context is a reference to SynchronizationContext.Current
    Context.Post(delegate
    {
        textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
    }, null)
);

매개 변수가 있는 서버에서 호출된 메서드에 대한 콘솔 애플리케이션 클라이언트 코드

stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => 
    Console.WriteLine("Symbol {0} Price {1}", stock.Symbol, stock.Price));

매개 변수가 있는 메서드, 매개 변수에 대한 동적 개체 지정

매개 변수에 동적 개체를 사용하여 매개 변수가 있는 서버에서 호출된 메서드에 대한 WPF 클라이언트 코드

stockTickerHubProxy.On("UpdateStockPrice", stock => 
    Dispatcher.InvokeAsync(() =>
        {
            textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
        })
);

매개 변수에 동적 개체를 사용하여 매개 변수가 있는 서버에서 호출되는 메서드에 대한 Silverlight 클라이언트 코드

stockTickerHubProxy.On("UpdateStockPrice", stock => 
    // Context is a reference to SynchronizationContext.Current
    Context.Post(delegate
    {
        textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price);
    }, null)
);

매개 변수에 동적 개체를 사용하여 매개 변수가 있는 서버에서 호출되는 메서드에 대한 콘솔 애플리케이션 클라이언트 코드

stockTickerHubProxy.On("UpdateStockPrice", stock => 
    Console.WriteLine("Symbol {0} Price {1}", stock.Symbol, stock.Price));