Meilleur auteur de réponses
Appel asynchrone+multithreading = NullReferenceException :(

Question
-
Bonsoir,
je désire faire un appel asynchrone vers un webservice mappoint, j'opère donc de la manière suivante:
Stream imageStream; // variable globale
void DisplayMap(double latitude,double longitude)
{
// du code...
RenderServiceSoap rss;
rss.BeginGetMap(mapSpecif, new AsyncCallback(GetMapThread), rss);
}
private void GetMapThread(IAsyncResult state)
{
RenderServiceSoap rss = state.AsyncState as RenderServiceSoap;
if (rss == null)
return;
MapImage[] images = rss.EndGetMap(state);
imageStream = new System.IO.MemoryStream(images[0].MimeData.Bits);
}
// puis au niveau de ma fct principale
DisplayMap(pos_lat,pos_long);
pictureBox1.Image=new System.Drawing.Bitmap(imageStream); //la varia ble globale devrait être mis à jour à l'intérieur de GetMapThread
A l'execution j'obtiens une exception de type NullReferenceException, donc voici le détail :
StackTrace " at System.Drawing.Bitmap..ctor(Stream stream)\r\n at PickMeUp.RiderStartSearch..ctor()\r\n at PickMeUp.RiderMainMenu.startsearch_SelectedIndexChanged(Object sender, EventArgs e)\r\n at System.Windows.Forms.ListView.OnSelectedIndexChanged(EventArgs e)\r\n at System.Windows.Forms.ListView.UpdateSelectedIndex(Int32 iItem)\r\n at System.Windows.Forms.ListView.WnProc(WM wm, Int32 wParam, Int32 lParam)\r\n at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)\r\n at Microsoft.AGL.Forms.EVL.EnterModalDialog(IntPtr hwnModal)\r\n at System.Windows.Forms.Form.ShowDialog()\r\n at PickMeUp.SelectMode.RiderMode_SelectedIndexChanged(Object sender, EventArgs e)\r\n at System.Windows.Forms.ListView.OnSelectedIndexChanged(EventArgs e)\r\n at System.Windows.Forms.ListView.UpdateSelectedIndex(Int32 iItem)\r\n at System.Windows.Forms.ListView.WnProc(WM wm, Int32 wParam, Int32 lParam)\r\n at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)\r\n at Microsoft.AGL.Forms.EVL.EnterModalDialog(IntPtr hwnModal)\r\n at System.Windows.Forms.Form.ShowDialog()\r\n at PickMeUp.FLogin.Login_Click(Object sender, EventArgs e)\r\n at System.Windows.Forms.Control.OnClick(EventArgs e)\r\n at System.Windows.Forms.Button.OnClick(EventArgs e)\r\n at System.Windows.Forms.ButtonBase.WnProc(WM wm, Int32 wParam, Int32 lParam)\r\n at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)\r\n at Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain)\r\n at System.Windows.Forms.Application.Run(Form fm)\r\n at PickMeUp.Program.Main()\r\n" string
Ce qui est bizarre c'est qu'un coup j'obtiens ça, un coup j'obtiens un NullReferenceException mais avec un message comme quoi je devrais utiliser Invoke..
"Control.Invoke must be used to interact with controls created on a separate thread." string
Je tiens à signaler que j'ai tenté d'utiliser un delegate de la manière suivante :
private delegate void GetMapThreadDelegate(IAsyncResult state);
private void DoUpdate2(IAsyncResult state)
{
if (this.InvokeRequired)
{
this.Invoke(new GetMapThreadDelegate(DoUpdate2),new object[] { state });
return;
}
MapImage[] images = rss.EndGetMap(state);
imageStream = new System.IO.MemoryStream(images[0].MimeData.Bits);
}
Avec la mise à jour effectuée dans GetMapThread ( qui appelle la méthode DoUpdate2 )
J'ai cherché sur le net de l'aide sur ce genre de msg d'erreur apparemment c'est assez connu comme problème, mais je n'ai pas su adapter les solutions trouvées à mon cas
Merci pour votre aide grandement appréciée !- Déplacé Ciprian Duduiala mercredi 18 mai 2011 13:38 (Origine :XML)
Réponses
-
Bonjour,
Pour le problème de la NullReferenceException, cela est du au fait que l'instruction "pictureBox1.Image = ..." est appelée avant que la variable globale soit mise à jour. En effet la méthode DisplayMap fait un appel asynchrone mais vous n'attendez pas la fin de cette appel pour utiliser imageStream.
Voila un proposition qui devrait marcher :
Code Snippetprivate Stream imageStream;
private void DisplayMap(double latitude, double longitude)
{
RenderServiceSoap rss;
rss.BeginGetMap(mapSpecif, new AsyncCallback(GetMapThread), rss);
}
private void GetMapThread(IAsyncResult state)
{
RenderServiceSoap rss = state.AsyncState as RenderServiceSoap;
if (rss == null)
{
return;
}
MapImage[] images = rss.EndGetMap(state);
imageStream = new System.IO.MemoryStream(images[0].MimeData.Bits);
if (pictureBox1.InvokeRequired)
{
pictureBox1.Invoke(new UpdateMap(UpdatePictureBox));
}
else
{
UpdatePictureBox();
}
}
private delegate void UpdateMapDelegate();
private void UpdatePictureBox()
{
pictureBox1.Image = new System.Drawing.Bitmap(imageStream);
}
Il ne vous reste plus qu'a appeler DisplayMap et attendre
Toutes les réponses
-
Bonjour,
Pour le problème de la NullReferenceException, cela est du au fait que l'instruction "pictureBox1.Image = ..." est appelée avant que la variable globale soit mise à jour. En effet la méthode DisplayMap fait un appel asynchrone mais vous n'attendez pas la fin de cette appel pour utiliser imageStream.
Voila un proposition qui devrait marcher :
Code Snippetprivate Stream imageStream;
private void DisplayMap(double latitude, double longitude)
{
RenderServiceSoap rss;
rss.BeginGetMap(mapSpecif, new AsyncCallback(GetMapThread), rss);
}
private void GetMapThread(IAsyncResult state)
{
RenderServiceSoap rss = state.AsyncState as RenderServiceSoap;
if (rss == null)
{
return;
}
MapImage[] images = rss.EndGetMap(state);
imageStream = new System.IO.MemoryStream(images[0].MimeData.Bits);
if (pictureBox1.InvokeRequired)
{
pictureBox1.Invoke(new UpdateMap(UpdatePictureBox));
}
else
{
UpdatePictureBox();
}
}
private delegate void UpdateMapDelegate();
private void UpdatePictureBox()
{
pictureBox1.Image = new System.Drawing.Bitmap(imageStream);
}
Il ne vous reste plus qu'a appeler DisplayMap et attendre
-
-
Re bonsoir,
Je vais encore avoir besoin de votre aide si possible
J'ai été confronté à un cas similaire mais cette fois il n'y a ni pictureBox ni rien.
Je vous montre l'ossature de mon code:
{
pixels = rss.EndConvertToPoint(state);
}
private
void DisplayMapFromCoordinates(){
// du code..
rss.BeginConvertToPoint(Coord, viewByBoundingLocation, width, height,
new AsyncCallback(ConvertToPointThread), rss); for (int j = 0; j < taille; j++){
PuhspinsPixels[j] = new PickMeUp_Mobile_BusinessLayers.PixelsCoordinates();
PuhspinsPixels[j].idDriverCarList = DriverCarList[j].idMotorist;
PuhspinsPixels[j].X = pixels[j].X;
PuhspinsPixels[j].Y = pixels[j].Y;
PuhspinsPixels[j].SetSizeOfTheObject(taille);
}
}
private void pictureBox2_Click_1(object sender, EventArgs e){
{
menuItem2.Text =
menuItem1.Text =
"" + MousePosition.Y; if ((MousePosition.X > (Pixels.X - 10)) && (MousePosition.X < (Pixels
.X + 5)) && ((MousePosition.Y > (Pixels
.Y + 21)) && (MousePosition.Y < (Pixels
.Y + 27))))
{
ClickDetected =
}
if (ClickDetected){
DriverDisplayed = i;
DisplayFirstPanel();
i = taille;
}
i++;
}
}
{
{
}
pictureBox2.Image =
new System.Drawing.Bitmap(imageStream);}
private void DoUpdate(int nb_positions){
{
return;
}
DisplayMapFromCoordinates();
}
private void CallPositionsThreading(){
{
DoUpdate(nb_positions);
}
}
Il me sort encore une exception de type : NullReferenceException. ( qui doit venir de Pixels qui doit être non intialisé.. ça doit être le même problème que la dernière fois, mais là je vois vraiment pas comment le résoudre ?
Merci bcp en tous cas !!
Bonjour,
Le problème est toujours le même, vous utilisez les données générées par votre fonction asynchrone avant que celle-ci n'est finit. Voila un exemple d'exécution pour vous expliquer le problème :
-
appel à rss.BeginConvertToPoint : pixels est null et un thread est lancé.
-
le système ne donne pas la main au nouveau thread mais continue le thread courant : début de la boucle for, pixels est null !
Comme pour le cas précédent, déplacé la boucle for après l'appel à BeginConvertToPoint à la fin de la méthode ConvertToPointThread. Dans ce cas vous êtes sur que pixels sera rempli.
Bonjour,
Merci encore une fois pour votre aide précieuse et efficace. Le problème du NullReference a été totalement réglé.
Mais, les thread n'ont malheureusement pas terminé de m'embêter!
Je vous expose mon nouveau problème (qui j'espère sera le dernier):
J'ai un thread : monThread qui appelle à chaque fois la fonction DisplayMap ( qui effectue des appels asynchrones aux webservices MapPoint comme vous avez pu le constater).
Le problème est qu'après deux appels de monThread, ce dernier n'est plus appelé ..
Je vous mets un bout de code:
|
Une idée? pourquoi le thread n'est pas appelé 15fois ? pourquoi se bloque t'il à 2 appels? pourquoi se bloque t'il tout court?
Je vous remercie pour votre aide et votre patience !!
(HS: Comment insérer une balise Snippet ? )