Silverlight 2 β2 で、WebHttpRequest や WebClient が、本当に非同期通信になりました。
うん。なんかね、「非同期通信にしか対応していないよ」と書いてあったのに、Silverlight 上ではスレッドが1つしかなかったのね。それが、UI Thread と、Communication Thread に分かれたの。
はい、何が起こるかわかるよね。Communication Thread で UI Elements を操作しようとすると、例外が発生しますorz...
それと、Uri 型だった WebClient.BaseAddress が、ただの文字列になりましたorz...
そんなわけで、第3回と、第4回のコードを書き直し。
まず、SyncronizationContect を用意します。その名の通り、同期するためのコンテキストです。こいつに、UI Thread を参照させます。そして、通信を受け取った後、UI Thread で通信の内容を転写します。
元ネタは、開発者さんのブログ。
では、書き直したコード。
// 同期コンテキスト
SynchronizationContext syncContext;
public Page() {
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded);
}
void Page_Loaded(object sender, RoutedEventArgs e) {
// 現在のコンテキストを参照させておく
syncContext = SynchronizationContext.Current;
WebClient client = new WebClient();
// ただの文字列なので、Uri に変換
Uri assmblUri = new Uri(client.BaseAddress);
// β1ではパスだったのに、.xap に変わっているので、パスに変換
string path = System.IO.Path.GetDirectoryName(assmblUri.LocalPath).Replace('\\', '/');
// スキーマやホストをつなげて URI にできる文字列にする
string uri = String.Format("{0}://{1}{2}/warnigLog.xml"
, assmblUri.Scheme, assmblUri.Host, path, assmblUri.AbsolutePath);
textBox1.Text = uri;
Uri logUri = new Uri(uri);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(logUri);
request.BeginGetResponse(new AsyncCallback(GetWarningLog), request);
}
private void GetWarningLog(IAsyncResult result) {
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
// 同期コンテキストから呼び出す
syncContext.Post(SynchronizedResponse, response);
}
private void SynchronizedResponse(object state) {
HttpWebResponse response = state as HttpWebResponse;
Stream stream = response.GetResponseStream();
try {
XmlSerializer serializer = new XmlSerializer(typeof(WarningLog));
log = (WarningLog)serializer.Deserialize(stream);
textBox1.Text += ":resieved\n";
foreach (Warning w in log.WarningList) {
textBox1.Text += (w.ToString() + "\n");
}
} catch (Exception ex) {
textBox1.Text = ex.ToString();
}
}
投稿日時 : 2008年6月12日 21:39