スレッドの1つが答えを見つけたとき(コンテキストはあまり重要ではないと思います)、多くのスレッドを使用するプログラムがあります-それを発表し、作成した最初のスレッドが Invoke を使用してユーザーコントロールクラスの関数を呼び出します. 確認しましたが、この関数の属性を変更すると、クロススレッド操作が行われません。しかし、この関数はタイマー(System.Timers.Timer)を開始します->そのため、「Elapsed」イベントの関数が呼び出されます。その中で属性を変更しようとしていますが、それによりクロススレッド操作が発生します。私は何を間違っていますか?呼び出された関数で別の関数を呼び出して、そこで属性を変更することはできませんか?
ところで、デリゲートを使って関数を呼び出すのは間違っていますか? つまり、必要なクラスの属性としてデリゲートを持ち、次に delegAttributeName.Invoke(parameters) を使用します - this.Invoke(new Delegate(), parameters); ではありません。
コードの一部を次に示します。
それが私が関数を呼び出す場所です:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Nim_Assignment_3
{
public delegate void drawDeleg(Color c, int amount, int rowNumber);
public partial class Nim : Form
{
private event drawDeleg myDrawDeleg;
private void CheckXor()
{
if (this.foundToPaint)
{
this.myDrawDeleg.Invoke(this.currentTurnColor, this.amountToPaint, this.rowToPaint);
this.drawWait.WaitOne();
this.foundToPaint = false;
if (this.currentTurnColor == Color.Blue)
this.currentTurnColor = Color.Red;
else
this.currentTurnColor = Color.Blue;
}
}
// the invoked function:
private void callFillPencils(Color c, int amount, int rowNumber)
{
this.rows[rowNumber].fillPencils(c, amount);
}
}
}
そして、これは呼び出された関数が呼び出している関数であり、それが呼び出す関数 (タイマー経過イベント関数) です: (fillPencils - Form クラス (Nim) で呼び出された関数が呼び出している関数):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Timers;
namespace Nim_Assignment_3
{
public partial class PencilsUC : UserControl
{
private PictureBox[] pencils;
public static Image grayPencil = new Bitmap("GrayPen.bmp"), bluePencil = new Bitmap("BluePen.bmp"), redPencil = new Bitmap("RedPen.bmp");
private int amountOfPencils, amountOfPencilsLeft, currIndex, currAmount;
private System.Timers.Timer timer;
private Color currColor;
public event FinishedDrawing drawFinishedDeleg;
public PencilsUC()
{
// intializing things in the constructor...
this.timer = new System.Timers.Timer();
this.timer.Interval = 100;
this.timer.Elapsed += new ElapsedEventHandler(timer_Tick);
}
public void timer_Tick(object sender, EventArgs e)
{
// THE THING THAT MAKES THE CROSS THREAD-OPERATION: THE LINE INSIDE THE "if"
if (this.currColor == Color.Blue)
pencils[currIndex--].Image = bluePencil;
else
pencils[currIndex--].Image = redPencil;
this.currAmount--;
if (this.currAmount == 0)
{
this.timer.Stop();
if (this.drawFinishedDeleg != null)
this.drawFinishedDeleg.Invoke(this, new EventArgs());
}
}
public void fillPencils(Color c, int amount)
{
MessageBox.Show("Hello");
this.currColor = c;
this.currAmount = amount;
this.timer.Start();
}
}
}
(クロス スレッド操作は、TIMER_TICK 関数内で発生します)
最初はWindowsフォームタイマーを使用しましたが、何らかの理由でtick-event関数に到達しませんでした(timer.Start()が呼び出されましたが、tick関数にメッセージボックスを入れましたが、そこに入らなかったので変更しましたそれ - 私はそれがより良いと言っているいくつかの答えを見ました)
助けていただければ幸いです。長い投稿で申し訳ありません。できるだけ明確にしたかっただけです...
よろしくお願いします!:)