[C#] Visual 2005 Beta 1 & Thread safe operation

Résolu
Signaler
Messages postés
714
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
19 janvier 2017
-
Messages postés
6351
Date d'inscription
samedi 1 juin 2002
Statut
Membre
Dernière intervention
2 août 2014
-
Actuellement en train de tester la compatiblité de mes appli sur .NET 2005, je rencontre un petit problème d'accès entre threads et dont je ne sais pas si cela vient plus du codage que du type d'accès.

En gros, G un thread principal (cad celui de mon appli qui contient une RichTextBox. Maintenant, j'ai un autre thread qui mouiline dans un coin et qui doit rajouter du text dans l'edit.

Si je met le code dans le 2nd thread, meme le fait de lire la longueur du texte de la RichEdit me fait peter une Exception de type operation entre thread blah blah.

Quelle est donc la meilleure solution ?

----------------------------
C++ forever
C# amateur

13 réponses

Messages postés
103
Date d'inscription
lundi 8 juillet 2002
Statut
Membre
Dernière intervention
24 novembre 2005

[font=Tahoma]
Je crois que tu oublies de passer tes arguments à DoPresentOnMainThread:
/font
 private void Runtime()
{
    this.richTextBox1.Invoke(new PresentHandler(this.DoPresentOnMainThread));
}


[font=Tahoma]
devrait être:
/font

private void Runtime()
{
    object[] args = new object[] {this.richTextBox1, "Main Thread : line 0" };
    this.richTextBox1.Invoke(new PresentHandler(this.DoPresentOnMainThread), args);
}
Messages postés
95
Date d'inscription
mardi 15 juin 2004
Statut
Membre
Dernière intervention
2 juin 2007

Bonjour je connais pas ton code mais peut etre que tes threads accedent en meme temps a une meme variable, essaye peut etre avec lock().
Messages postés
714
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
19 janvier 2017

Le lock() ne change rien sur .NET 2005

voici le code :

using System;
using System.Threading;
using System.Windows.Forms;

namespace QuickSample
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private RichTextBox richTextBox1;
private System.Threading.Thread myEngineThread;
private System.ComponentModel.IContainer m_components = null;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

// TODO: Add any constructor code after InitializeComponent call
WriteToOutput(richTextBox1, "Main Thread : line 0");

//myEngineThread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(this.Runtime));
myEngineThread = new System.Threading.Thread (new ThreadStart(this.Runtime));
this.myEngineThread.Start();

}

public void WriteToOutput(RichTextBox _oDst, string _szText)
{
_oDst.AppendText(_szText);
}

static readonly object countLock = new object();
private void Runtime()
{
// Illegal cross thread operation
lock (countLock)
{
richTextBox1.AppendText("toto");
}
//
// OU
//
// Parameter count mismatch
//this.richTextBox1.Invoke(new PresentHandler(this.DoPresentOnMainThread));
}

private delegate void PresentHandler(RichTextBox _oDst, string _szText);
private void DoPresentOnMainThread(RichTextBox _oDst, string _szText)
{
_oDst.AppendText(_szText);
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (m_components != null)
{
m_components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.SuspendLayout();
//
// richTextBox1
//
this.richTextBox1.Location = new System.Drawing.Point(28, 37);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(206, 176);
this.richTextBox1.TabIndex = 0;
this.richTextBox1.Text = "";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.richTextBox1);
this.Name = "Form1";
this.Text = "MyDialog";
this.ResumeLayout(false);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}
}
Messages postés
714
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
19 janvier 2017

rien changé :-(

----------------------------
C++ forever
C# amateur
Messages postés
103
Date d'inscription
lundi 8 juillet 2002
Statut
Membre
Dernière intervention
24 novembre 2005

Tu as toujours l'exception TargetParameterCountException? Parce qu'avec les modifications que j'ai faites ton code tourne sans problème.
Messages postés
714
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
19 janvier 2017

Heu vi ca marche mais faut pas mettre de Break Point sur le Invoke, c'est ca qui fait bacher.
Mais pk cela ? alors la aucune idee

----------------------------
C++ forever
C# amateur
Messages postés
103
Date d'inscription
lundi 8 juillet 2002
Statut
Membre
Dernière intervention
24 novembre 2005

Je crois que c'est un bug de VS Beta 1, si tu poses un breakpoint sur Invoke et que tu avance à la ligne suivant ca passe, mais si tu inspecte un contrôle de ta feuille (comme ici richTextBox1), il va appeller ToString du contrôle, ce qui va lancer une exception de synchronisation que tu te récupère après l'appel à Invoke.
Je l'ai posté dans le MSDN Feedback Center.
Messages postés
9
Date d'inscription
jeudi 27 janvier 2005
Statut
Membre
Dernière intervention
31 décembre 2005

Salut,
Est ce que ton souci d'acces entre threads a été résolu.
J'ai eu à un moment un souci similaire que j'ai resolu.
exemple de code:


//Dans vs2005 pour pas avoir le message d’erreur « Illegal cross thread operation »<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />





/* Dans le Thread principal */


//Declaration du contrôle


PictureBox grWatch = new PictureBox() ;


//initialisations des proprietes du contrôle





//Propriete du UserControl qui donne l’acces à Picture.Graphics


private Graphics WatchGraphics


{


get { return (Graphics)Invoke(new GetWatchGraphicsDelegate(GetWatchGraphics)); }


}


//Delegate et sa fonction associée


//Ils permettent d’acceder au menbres d’un contrôle à partir d’un thread qui ne l’a pas créer


private delegate Graphics GetWatchGraphicsDelegate();


private Graphics GetWatchGraphics()


{


return grWatch.CreateGraphics();


}





/* Dans le Thread du timer */


//Au moment de l’acces


bg = bgc.Allocate( WatchGraphics , new Rectangle(0, 0, WatchGraphicsWidth, WatchGraphicsHeight));

[mailto:mox@hotmail.fr mox@hotmail.fr]
Messages postés
18
Date d'inscription
jeudi 13 février 2003
Statut
Membre
Dernière intervention
12 mars 2008

Y'a mieux, mais avec beaucoup moins de sécurité pour le problème Illegal Cross Threading

Ajouté ça dans le Load : Control.CheckForIllegalCrossThreadCalls=false

Ca enlève la securité sur le frameword 2.0

Bien cordialement

Olivier
Messages postés
714
Date d'inscription
mardi 22 avril 2003
Statut
Membre
Dernière intervention
19 janvier 2017

oui je connaissais, c'est pour du portage de code façon porscasse. A eviter au possible.

----------------------------
C++ forever
C# amateur
Messages postés
6351
Date d'inscription
samedi 1 juin 2002
Statut
Membre
Dernière intervention
2 août 2014
98
Salut,

olecossois >
Ce qui a pour effet de masquer le problème et non le résoudre...
Le mieux est donc naturellement de passer par ce qui est décrit par exemple dans ce tuto : OPÉRATIONS CROSS THREADS - UTILISATION DES DELEGATIONS SYNCHRONES / ASYNCHRONES

/*
coq
MVP Visual C#
CoqBlog
*/
Messages postés
18
Date d'inscription
jeudi 13 février 2003
Statut
Membre
Dernière intervention
12 mars 2008

Je suis complètement d'accord, que ça ne résoud pas le problème, ça ne fait que le contourner, évidemment, le mieux étant de le résoudre, mais pour une action rapide, pour vérification, ça peut être pratique

Olivier
Messages postés
6351
Date d'inscription
samedi 1 juin 2002
Statut
Membre
Dernière intervention
2 août 2014
98
Oui , c'était surtout pour être sûr que personne ne prenne ça comme solution viable :-)

/*
coq
MVP Visual C#
CoqBlog
*/