7

引数を使用してスレッドでメソッドを呼び出し、ここで値を返すのが好きです例

class Program
{
    static void Main()
    {
        Thread FirstThread = new Thread(new ThreadStart(Fun1));
        Thread SecondThread = new Thread(new ThreadStart(Fun2));
        FirstThread.Start();
        SecondThread.Start();
    }
    public static void Fun1()
    {
        for (int i = 1; i <= 1000; i++)
        {
            Console.WriteLine("Fun1 writes:{0}", i);
        }
    }
    public static void Fun2()
    {
        for (int i = 1000; i >= 6; i--)
        {
            Console.WriteLine("Fun2 writes:{0}", i);
        }
    }
}

上記の例が正常に実行されることはわかっていますが、メソッド fun1 がこのように

public int fun1(int i,int j)
{
    int k;
    k=i+j;
    return k;
}

では、どうすればこれをスレッドで呼び出すことができますか?

4

7 に答える 7

24

匿名メソッドまたはラムダを使用して、完全な静的チェックを提供できるはずです。

Thread FirstThread = new Thread(() => Fun1(5, 12));

または、結果を使って何かをしたい場合:

Thread FirstThread = new Thread(() => {
    int i = Fun1(5, 12);
    // do something with i
});

ただし、この「何かを行う」は、新しいスレッドのコンテキストで引き続き実行されることに注意してください(ただし、Main「キャプチャされた変数」のおかげで、外部メソッド()の他の変数にアクセスできます)。

C#2.0を使用している場合(上記ではない場合)、次のようになります。

Thread FirstThread = new Thread((ThreadStart)delegate { Fun1(5, 12); });

Thread FirstThread = new Thread((ThreadStart)delegate {
    int i = Fun1(5, 12);
    // do something with i
});
于 2010-04-15T05:56:24.900 に答える
7

これは別のアプローチかもしれません。ここで、入力はパラメーター化されたスレッドとして渡され、戻り値の型はデリゲート イベントで渡されるため、スレッドが完了するとデリゲートが呼び出されます。これは、スレッドが完了したときに結果を取得するのに問題ありません。

 public class ThreadObject
    {
        public int i;
        public int j;
        public int result;
        public string Name;
    }



    public delegate void ResultDelegate(ThreadObject threadObject);

    public partial class Form1 : Form
    {

        public event ResultDelegate resultDelete;

        public Form1()
        {
            InitializeComponent();

            resultDelete += new ResultDelegate(resultValue);
        }

        void resultValue(ThreadObject threadObject)
        {
            MessageBox.Show("Thread Name : " + threadObject.Name + " Thread Value : " + threadObject.result);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ThreadObject firstThreadObject = new ThreadObject();
            firstThreadObject.i = 0;
            firstThreadObject.j = 100;
            firstThreadObject.Name = "First Thread";

            Thread firstThread = new Thread(Fun);
            firstThread.Start(firstThreadObject);


            ThreadObject secondThreadObject = new ThreadObject();
            secondThreadObject.i = 0;
            secondThreadObject.j = 200;
            secondThreadObject.Name = "Second Thread";

            Thread secondThread = new Thread(Fun);
            secondThread.Start(secondThreadObject);

        }


        private void Fun(object parameter)
        {
            ThreadObject threadObject = parameter as ThreadObject;

            for (; threadObject.i < threadObject.j; threadObject.i++)
            {
                threadObject.result += threadObject.i;

                Thread.Sleep(10);
            }

            resultValue(threadObject);
        }
    }
于 2010-04-21T12:13:45.753 に答える
7

Mark Gravellの答えが好きです。少し変更するだけで、結果をメイン スレッドに戻すことができます。

int fun1, fun2;
Thread FirstThread = new Thread(() => {
    fun1 = Fun1(5, 12);
});
Thread SecondThread = new Thread(() => {
    fun2 = Fun2(2, 3); 
});

FirstThread.Start();
SecondThread.Start();
FirstThread.Join();
SecondThread.Join();

Console.WriteLine("Fun1 returned {0}, Fun2 returned {1}", fun1, fun2);
于 2011-04-19T17:31:01.357 に答える
1

別のスレッドで関数を実行するもっと簡単な方法があります。

// Create function delegate (it can be any delegate)
var FunFunc = new Func<int, int, int>(fun1);
// Start executing function on thread pool with parameters
IAsyncResult FunFuncResult = FunFunc.BeginInvoke(1, 5, null, null);
// Do some stuff
// Wait for asynchronous call completion and get result
int Result = FunFunc.EndInvoke(FunFuncResult);

この関数はスレッドプールスレッドで実行され、そのロジックはアプリケーションに対して完全に透過的です。一般に、このような小さなタスクは、専用スレッドではなくスレッドプールで実行することをお勧めします。

于 2010-04-23T09:02:06.963 に答える
0

Thread コンストラクターで ParameterizedThreadStart オーバーロードを使用できます。オブジェクトをパラメーターとしてスレッド メソッドに渡すことができます。これは単一のオブジェクト パラメータになるため、通常はそのようなスレッド用のパラメータ クラスを作成します。このオブジェクトは、スレッド実行の結果を格納することもでき、スレッドの終了後に読み取ることができます。

スレッドの実行中にこのオブジェクトにアクセスすることは可能ですが、「スレッドセーフ」ではないことを忘れないでください。あなたはドリルを知っています:)

次に例を示します。

void Main()
{
    var thread = new Thread(Fun);
    var obj = new ThreadObject
    {
        i = 1,
        j = 15,
    };

    thread.Start(obj);
    thread.Join();
    Console.WriteLine(obj.result);
}

public static void Fun(Object obj)
{
    var threadObj = obj as ThreadObject;
    threadObj.result = threadObj.i + threadObj.j;
}

public class ThreadObject
{
    public int i;
    public int j;
    public int result;
}
于 2010-04-21T09:57:17.210 に答える
0

backgroundWorker http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspxを試してみてください。DoWorkEventArgs を使用して DoWork イベントに値を渡し、RunWorkerCompleted で値を取得できます。

于 2010-04-23T09:53:54.710 に答える
0

いくつかの代替案については; カリー化:

static ThreadStart CurryForFun(int i, int j)
{ // also needs a target object if Fun1 not static
    return () => Fun1(i, j);
}

Thread FirstThread = new Thread(CurryForFun(5, 12));

または、独自のキャプチャ タイプを記述します (これは、キャプチャされた変数で anon-methods / lambdas を使用するときにコンパイラが行うこととほぼ同じですが、実装方法が異なります)。

class MyCaptureClass
{
    private readonly int i, j;
    int? result;
    // only available after execution
    public int Result { get { return result.Value; } }
    public MyCaptureClass(int i, int j)
    {
        this.i = i;
        this.j = j;
    }
    public void Invoke()
    { // will also need a target object if Fun1 isn't static
        result = Fun1(i, j);
    }
}
...
MyCaptureClass capture = new MyCaptureClass(5, 12);
Thread FirstThread = new Thread(capture.Invoke);
// then in the future, access capture.Result
于 2010-04-21T10:07:01.827 に答える