DOBON.NET DOBON.NETプログラミング掲示板過去ログ

C# でgetLatLngを読んだがコールバックされない

環境/言語:[C#2008 & Javascript]
分類:[.NET]

いつも参考にさせていただいています。

現在、C#から、webBrowser コントロール経由で、Google MAP API の getLatLng APIを呼び出して、住所から GPS のポイントを取得する処理を作成しています。
悩みは、このgetLatLngってAPIは非同期処理で処理が完了する前に関数を抜けてきて、結果として、webBrowser上の Javascript から C# に制御が返ってきちゃいます。
一応、getLatLng API にはコールバック関数を指定してそこにイベントが発生するようになっていますが、Javascript 単体でテストすると動くのですが、C#側からキックしてやると、コールバックができないんですよね。
ちなみに、Javascript側で、alert() を実行して一瞬止めるとC# にまでコールバックされる事は確認しているのですが、用もないのに alert()は使用したくないし・・・。

下記ロジックは基本的な部分は、問題ないと思います。
でも、意図どうりにコールバックさせるには何かが足りない。

何かいいアイデアはありませんかね?

/********* C# 側 ********/

とある関数の中 ()
{
object[] args = new object[] { add }; // add = 文字列の住所
object str = this.webBrowser1.Document.InvokeScript("GetAddress", args); // Javascriptの関数をキック
}

public void GetGoogleMapGpsEvt(string message) // javaScriptからのコールバック
{
Console.WriteLine("ReturnGPS=" + message);
GoogleMapEvt = 0;
}

/***** JavaScript側 **********/

function GetAddress(add)
{
geocoder = new GClientGeocoder();

//alert( add );
geocoder.getLatLng( add , Sub_GetGps );
//alert( "getLatLng Exit !" );

}


function Sub_GetGps(point)
{
alert( "Sub_GetGps( " + point + " )");
if( !point )
{
//alert( point + " NG !!" );
}
else
{
map.setCenter(point, 14);
var marker = new GMarker(point);
map.addOverlay(marker);
//alert( point + " OK !!" );
}
window.external.GetGoogleMapGpsEvt( point ); // GPSのPOINT をお土産にして C# の関数をキックてやる。
}
■No23971に返信(Keiさんの記事)
> window.external.GetGoogleMapGpsEvt( point );
という事は、C# 側で
 webBrowser1.ObjectForScripting = this;
のような事を行っているという事でしょうか。


> C#側からキックしてやると、コールバックができないんですよね。
JavaScript 側からキックした場合は、C# にまでコールバックが届くのですね?

私は Google MAP API の仕様を知らないので、外しているかもしれませんが、
「コールバックができない」というのは、
 (a) Sub_GetGps は呼ばれるが、C# 側には通知されない。
 (b) Sub_GetGps 自体が呼ばれない。
のいずれでしょうか?


もしも (a) だとしたら、window.external.GetGoogleMapGpsEvt が、
何らかの理由で失敗しているのかも知れません。
external 以外の方法で通信した場合はどうなりますか?

 // ブラウザ側
 <input type="button" style="display:none" id="btn1">
 function Sub_GetGps(point)
 {
   :
  btn1.value = point;
  btn1.click();
 }

 // C# 側
 void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
 {
  webBrowser1.Document.GetElementById("btn1").AttachEventHandler("onclick", btn1_onclick);
 }
 void btn1_onclick(Object sender, EventArgs e)
 {
  object oPoint = webBrowser1.Document.GetElementById("btn1").GetAttribute("value");
 }


> alert() を実行して一瞬止めるとC# にまでコールバックされる
alert を実行させたのは、GetAddress(add) でしょうか。
それとも、Sub_GetGps(point) でしょうか。
■No23974に返信(魔界の仮面弁士さんの記事)
> ■No23971に返信(Keiさんの記事)
ども、大変お世話になります。


> webBrowser1.ObjectForScripting = this;
>のような事を行っているという事でしょうか。

はい、その通りです。



>> C#側からキックしてやると、コールバックができないんですよね。
>JavaScript 側からキックした場合は、C# にまでコールバックが届くのですね?

はい、その通りです。
で、しかし、C# でキックしてから、javascript 側で、getLatLng() の実行直後
に alert を実行してみるとコールバックが機能する・・・。
まぁこのalert もデバッグの為に入れ込んだらたまたまそのような現象を
確認することが出来たって訳なんです。


>私は Google MAP API の仕様を知らないので、外しているかもしれませんが、

getLatLng()のAPI は、引数に、検索対象の住所とコールバック先の関数を
指定するようになっています。 で、住所からGPSのPointに変換するには
時間がかかるので、非同期処理でコールバックしてやる・・・って思想なんだと
思います。


>「コールバックができない」というのは、
> (a) Sub_GetGps は呼ばれるが、C# 側には通知されない。
> (b) Sub_GetGps 自体が呼ばれない。
>のいずれでしょうか?

(b)になります。

例の Sub_GetGps() に記述してあるとおりですと、テスト用に設置した
alert() によりメッセージが表示されます。

Sub_GetGps()が呼ばれると、window.external.GetGoogleMapGpsEvt( point );
が実行され、C#側の関数がキックされる事を確認しています。
つまり、javascript 側で、Sub_GetGps()に対するコールバックが
効いていない事になります。



>もしも (a) だとしたら、window.external.GetGoogleMapGpsEvt が、
>何らかの理由で失敗しているのかも知れません。
>external 以外の方法で通信した場合はどうなりますか?

すいません。
出先からなので実験できません。
帰ったら実験してみます。


>alert を実行させたのは、GetAddress(add) でしょうか。
>それとも、Sub_GetGps(point) でしょうか。

例だと、
showAddress()側で、getLatLng() を実行した後です。
実行前に alert で一旦停止しても効果が無い事を確認
しており、getLatLng() を実行して、そこから非同期
処理になった以降に alert を実行すると getLatLng() の引数
で指定したコールバック関数が呼ばれるようになる・・・
みたいな感じです。



まさかとは思いますが、webBrowser コントロールの仕様として、
Javascript は動作できるが、一度、C# に制御が戻ってくると、
javascript 側は完全に停止してしまって、それが理由でjavascript 側で
コールバックを設定していても、javascript が動作していない以上は
にっちもさっちもいかない・・・って事はないのかなぁ・・・。
ま、まさかね・・・。
■No23975に返信(Keiさんの記事)
> ■No23974に返信(魔界の仮面弁士さんの記事)
>>■No23971に返信(Keiさんの記事)
> ども、大変お世話になります。
>

どもども、お世話になっております。

さて、この事案ですが、解決しました。

ロジックは正しかったです。

で、何が悪かったかと言うと、何も悪くもありませんでした・・・。

住所から GPS のPOINT に変換した後、一度制御が C# 側に戻って
きた後の、javascript 側のコールバックが、想定以上にとんでもなく遅い・・・。
私が待ちきれなかっただけの話でした。

ただ、住所を大量に送信してやると、送信し続けている間は、コールバックされない事が判りました。
Javascriptのみでロジック組んで実験した時は住所を送信するたびにPOINTに変換されてコールバックされますが、C#からJavascriptをキックするとどういう訳か、一呼吸も二呼吸もしないとコールバックされないっぽ・・・。
溜め込んだバッファを吐き出すかのように、大量のコールバックが返ってきちゃう・・・。
まぁ一応、問題は解決はしたものの、なんだかなぁ・・・・って感じです。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板