[PR]
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
プログラミング、3DCGとその他いろいろについて
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
using System.ServiceModel;
namespace Contracts
{
[ServiceContract]
public interface ICalculator
{
//四角形の面積を計算します
[OperationContract]
double GetArea(Rectangle rect);
}
//Error!
//(throws InvalidDataContractException)
public class Rectangle
{
public double Width;
public double Height;
}
}
using System.ServiceModel;
namespace Contracts
{
[ServiceContract]
public interface ICalculator
{
//四角形の面積を計算します
[OperationContract]
double GetArea(Rectangle rect);
}
[System.Serializable]
public class Rectangle
{
public double Width;
public double Height;
}
}
using System;
using System.ServiceModel;
using Contracts;
namespace Server
{
class MyCalculator : ICalculator
{
public double GetArea(Rectangle rect)
{
return rect.Width * rect.Height;
}
}
class Program
{
static void Main(string[] args)
{
ServiceHost serviceHost = new ServiceHost(typeof(MyCalculator));
serviceHost.AddServiceEndpoint(
typeof(ICalculator),
new NetTcpBinding(),
"net.tcp://localhost:8001/Calculator"
);
serviceHost.Open();
Console.WriteLine("サービスがオープンしました。終了するにはEnterを押してください。");
Console.ReadLine();
serviceHost.Close();
}
}
}
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Contracts;
namespace Client
{
class Program
{
static void Main(string[] args)
{
ICalculator remoteService = new ChannelFactory (
new NetTcpBinding(),
"net.tcp://localhost:8001/Calculator"
).CreateChannel();
Console.WriteLine(
"2 * 3 = "
+ remoteService.GetArea(new Rectangle{Width = 2, Height = 3})
);
((IChannel)remoteService).Close();
}
}
}
using System.ServiceModel;
namespace Contracts
{
[ServiceContract]
public interface ICalculator
{
//四角形の面積を計算します
[OperationContract]
double GetArea(Rectangle rect);
}
[System.Runtime.Serialization.DataContract]
public class Rectangle
{
[System.Runtime.Serialization.DataMember]
public double Width;
[System.Runtime.Serialization.DataMember]
public double Height;
}
}
using System;
using System.ServiceModel;
namespace Server
{
[ServiceContract]
interface ICalculator
{
[OperationContract]
int Add(int a, int b);
}
class MyCalculator : ICalculator
{
public int Add(int a, int b)
{
return a + b;
}
}
class Program
{
static void Main()
{
ServiceHost serviceHost = new ServiceHost(typeof(MyCalculator));
serviceHost.AddServiceEndpoint(
typeof(ICalculator),
new NetTcpBinding(),
"net.tcp://localhost:8001/Calculator"
);
serviceHost.Open();
Console.WriteLine("サービスがオープンしました。終了するにはEnterを押してください。");
Console.ReadLine();
serviceHost.Close();
}
}
}
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace Client
{
[ServiceContract]
interface ICalculator
{
[OperationContract]
int Add(int a, int b);
}
class Program
{
static void Main()
{
ICalculator remoteCalculator = new ChannelFactory<ICalculator>(
new NetTcpBinding(),
"net.tcp://localhost:8001/Calculator"
).CreateChannel();
Console.WriteLine("2 + 3 = " + remoteCalculator.Add(2, 3));
((IChannel)remoteCalculator).Close();
}
}
}
public ServiceHost
(
Type serviceType,
params Uri[] baseAddresses
)
public ServiceEndpoint AddServiceEndpoint
(
Type implementedContract,
Binding binding,
string address
)
public ChannelFactory
(
Binding binding,
string remoteAddress
)
public TChannel CreateChannel()
先日WPFとWCFで遊んでいたらこれにはまったのでメモしておきます。
WCFのサーバーをコンソールアプリケーションで作り、クライアントをWPFで作っていたのですが、クライアントからサービスオブジェクトのメソッドを呼ぶと固まって、System.TimeoutExceptionがスローされてしまうのです(WCFでは、デフォルトで1分以内に向こう側から呼ばれたメソッドの処理が終わらないとTimeoutExceptionがスローされます)。
実のところこの原因は難しいことではなく、WCFのコールバックオブジェクトのイベント内(UIとは別スレッド)でWPFのButton.Contentを直接変更しようとしたために起きた問題で、Button.Dispatcher.BeginInvokeメソッドで簡単に解決する問題でした。
そうですそうです確かこれはWindows.Formsでも同じことをやった記憶があります。全く進歩がありません。こんなことをブログに書くのは恥ずかしいのですが、ある程度の範囲内なら、より痛い目にあえばより記憶が強力になるような気がしなくもないですからね。
コード
サーバー側のコードには問題がなかったのでクライアント側のコードだけを書きます(恥さらしは少ない方がいい!!)。
が、その前にどんな事をしようとしていたのかを簡単に説明しておきましょう。作ろうとしていたのは簡単なゲームで、プレイヤーは2人、それぞれのプレイヤーには最初に20点のライフと自分自身のウィンドウが与えられ、プレイヤーは自分のウィンドウのボタンを押すことで相手のライフを3減らすことができます。自分のライフが0になったら負けなので、ボタンをなるべく連打して相手のライフを早く0にしようとします。遊ぶ時にはそれぞれのプレイヤーは別々のパソコンを使うことになるのでしょう(そのためのWCFです)。そして、ボタンのクリックの速さを競うわけです。
ゲームとしては全然面白くない気がしますが、WCFの練習ならこういうのもいいんじゃないのかなぁと言い訳をしておきます。WPFとWCFに慣れたらもうちょっとフクザツにできるはずですからね。もしかしたらMagic : The Gatheringみたいにできるかもしれません。
で、問題のコードですが、これでした:
player.LifeChanged += delegate
{
this.YourLifeButton.Content = player.GetLife();
};
player.LifeChanged += delegate
{
YourLifeButton.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Background,
(System.Action)delegate
{
YourLifeButton.Content = player.GetLife();
}
);
};