スレッドから値を返しますか?


回答:


94

スレッドから戻り値を取得する最も簡単な方法の1つは、クロージャーを使用することです。スレッドからの戻り値を保持する変数を作成し、ラムダ式にキャプチャします。ワーカースレッドからこの変数に「戻り」値を割り当て、そのスレッドが終了すると、親スレッドからそれを使用できます。

void Main()
{
  object value = null; // Used to store the return value
  var thread = new Thread(
    () =>
    {
      value = "Hello World"; // Publish the return value
    });
  thread.Start();
  thread.Join();
  Console.WriteLine(value); // Use the return value here
}

3
思いませんlock(value) { value = "Hello world"; }複数のスレッド値の書き込みを処理する際の方が良いですか?
チェックサム

4
@checksum:この特定のケースでは、読み取りまたは書き込みvalueが同時に行われていないため不要です。ただし、ええ、ロックが必要な場合は常に注意してください。
ブライアンギデオン

素晴らしいアイデア!見事に機能し、受け入れられる答えになるはずです。
MerseyViking

34

スレッドの作成方法と使用可能な.NETバージョンによって異なります。

.NET 2.0以降:

A)Threadオブジェクトを直接作成できます。この場合、「閉鎖」を使用できます-変数を宣言し、ラムダ式を使用してそれをキャプチャします。

object result = null;
Thread thread = new System.Threading.Thread(() => { 
    //Some work...
    result = 42; });
thread.Start();
thread.Join();
Console.WriteLine(result);

B)デリゲートとメソッドIAsyncResultからの戻り値を使用できますEndInvoke()

delegate object MyFunc();
...
MyFunc x = new MyFunc(() => { 
    //Some work...
    return 42; });
IAsyncResult asyncResult = x.BeginInvoke(null, null);
object result = x.EndInvoke(asyncResult);

C)BackgroundWorkerクラスを使用できます。この場合、キャプチャされた変数(Threadオブジェクトなど)を使用するか、RunWorkerCompletedイベントを処理します。

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) => {
    //Some work...
    e.Result = 42;
};
worker.RunWorkerCompleted += (s, e) => {
    //e.Result "returned" from thread
    Console.WriteLine(e.Result);
};
worker.RunWorkerAsync();

.NET 4.0以降:

.NET 4.0以降では、タスク並列ライブラリTaskクラスを使用してスレッドを開始できます。ジェネリッククラスをTask<TResult>使用すると、Resultプロパティから戻り値を取得できます。

//Main thread will be blocked until task thread finishes
//(because of obtaining the value of the Result property)
int result = Task.Factory.StartNew(() => {
    //Some work...
    return 42;}).Result;

.NET 4.5以降:

.NET 4.5以降では、プロパティを取得する代わりにasync/ awaitキーワードを使用してタスクから直接値を返すこともできResultます。

int result = await Task.Run(() => {
    //Some work...
    return 42; });

注:上記のコードを含むメソッドは、 asyncキーワードます。

多くの理由により、タスク並列ライブラリの使用はスレッドを操作する好ましい方法です。


33

BackgroundWorkerを使用しますアプローチを、結果をe.Resultに返します。

編集:

これは一般にWinFormsとWPFに関連付けられていますが、あらゆる種類の.NETアプリケーションで使用できます。以下は、BackgroundWorkerを使用するコンソールアプリのサンプルコードです。

using System;
using System.Threading;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;

namespace BGWorker
{
    class Program
    {
        static bool done = false;

        static void Main(string[] args)
        {
            BackgroundWorker bg = new BackgroundWorker();
            bg.DoWork += new DoWorkEventHandler(bg_DoWork);
            bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
            bg.RunWorkerAsync();

            while (!done)
            {
                Console.WriteLine("Waiting in Main, tid " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(100);
            }
        }

        static void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Console.WriteLine("Completed, tid " + Thread.CurrentThread.ManagedThreadId);
            done = true;
        }

        static void bg_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 5; i++)
            {
                Console.WriteLine("Work Line: " + i + ", tid " + Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(500);
            }
        }
    }
}

出力:

Waiting in Main, tid 10
Work Line: 1, tid 6
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Work Line: 2, tid 6
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Work Line: 3, tid 6
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Work Line: 4, tid 6
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Work Line: 5, tid 6
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Waiting in Main, tid 10
Completed, tid 6

2014更新

以下の@Rogerの回答を参照してください。

https://stackoverflow.com/a/24916747/141172

彼は、を返すタスクを使用してTask<T>チェックできると指摘していますTask<T>.Result


はい。ただし、WinFormsとWPFにのみ適用されます。
ヘンクホルターマン

@ヘンク:真実ではない。念のため、BackgroundWorkerを使用したシンプルなコンソールアプリを作成しました:-)そのコードで投稿を編集しました。
エリックJ.

Eric、コードにいくつかの書き込み行を入れて、いつ何が発生し、どのThreadIdが発生するかを確認します。期待通りに行かないかもしれません。(完了はDoworkが完了する前に実行され、メインスレッドでは実行されません)。BgwにはMessagePumpが必要です。
ヘンクホルターマン

@ヘンク:あなたは半分正しいです。CompletedはBackgroundWorkerと同じスレッドで実行されますが、DoWorkの完了後に実行されます。編集した回答の出力を参照してください。
エリックJ.

2
正確に1つのスレッドが変数を設定し、正確に1つのスレッドが変数を読み取るため、競合状態はありません。コードの正しい実行には、セットと読み取りの正確な順序は関係ありません(つまり、メインスレッドで終了条件が発生する可能性があります)スレッドがスケジュールされている順序に応じて少し早くまたは遅くなりますが、どちらの方法でも正しい結果が得られます)。
エリックJ.

21

スレッドはメソッドではありません。通常、値を「返す」ことはありません。

ただし、いくつかの処理の結果から値をフェッチしようとする場合、多くのオプションがあり、主な2つのオプションは次のとおりです。

  • 共有データを同期して、適切に設定できます。
  • また、なんらかの形式のコールバックでデータを返すこともできます。

スレッドをどのように作成しているか、どのように使用したいか、そして使用している言語/フレームワーク/ツールに依存します。


15

私のお気に入りのクラスは、わずか2行のコードで別のスレッドで任意のメソッドを実行します。

class ThreadedExecuter<T> where T : class
{
    public delegate void CallBackDelegate(T returnValue);
    public delegate T MethodDelegate();
    private CallBackDelegate callback;
    private MethodDelegate method;

    private Thread t;

    public ThreadedExecuter(MethodDelegate method, CallBackDelegate callback)
    {
        this.method = method;
        this.callback = callback;
        t = new Thread(this.Process);
    }
    public void Start()
    {
        t.Start();
    }
    public void Abort()
    {
        t.Abort();
        callback(null); //can be left out depending on your needs
    }
    private void Process()
    {
        T stuffReturned = method();
        callback(stuffReturned);
    }
}

使用法

    void startthework()
    {
        ThreadedExecuter<string> executer = new ThreadedExecuter<string>(someLongFunction, longFunctionComplete);
        executer.Start();
    }
    string someLongFunction()
    {
        while(!workComplete)
            WorkWork();
        return resultOfWork;
    }
    void longFunctionComplete(string s)
    {
        PrintWorkComplete(s);
    }

longFunctionCompleteはstartheworkと同じスレッドで実行されないことに注意してください。

パラメータを取るメソッドの場合は、常にクロージャを使用するか、クラスを拡張できます。


3
すべての人にとって明確ではない... stuffReturned?、resultOfWork、PrintWorkComplete?など
Lost_In_Library '07 / 07/12

14

以下はデリゲートを使用した簡単な例です...

void Main()
{
   DoIt d1 = Doer.DoThatThang;
   DoIt d2 = Doer.DoThatThang;

   IAsyncResult r1 = d1.BeginInvoke( 5, null, null );
   IAsyncResult r2 = d2.BeginInvoke( 10, null, null );

   Thread.Sleep( 1000 );

   var s1 = d1.EndInvoke( r1 );
   var s2 = d2.EndInvoke( r2 );

   s1.Dump(); // You told me 5
   s2.Dump(); // You told me 10
}

public delegate string DoIt( int x );

public class Doer
{
  public static string DoThatThang( int x  )
  {
    return "You told me " + x.ToString();
  }
}

C#のスレッディングにはスレッディングに関する素晴らしいシリーズがあります。


9

デリゲートアプローチを使用するだけです。

int val;
Thread thread = new Thread(() => { val = Multiply(1, 2); });
thread.Start();

次に、別のスレッドで機能する乗算関数を作成します。

int Multiply(int x, int y)
{
    return x * y;
}

3
以下の「テキストファイルに保存して取得する」の回答はなぜですか?
ジョン

7

スレッド内で実行されるメソッドの戻り値を取得しようとしたときに、このスレッドに遭遇しました。私はうまくいく私の解決策を投稿すると思いました。

このソリューションでは、クラスを使用して(間接的に)実行するメソッドと戻り値を格納します。クラスは、任意の関数と任意の戻り値の型に使用できます。戻り値の型を使用してオブジェクトをインスタンス化し、ラムダ(またはデリゲート)を介して呼び出す関数を渡すだけです。


C#3.0の実装


public class ThreadedMethod<T>
{

    private T mResult;
    public T Result 
    {
        get { return mResult; }
        private set { mResult = value; }
    }

    public ThreadedMethod()
    {
    }

    //If supporting .net 3.5
    public void ExecuteMethod(Func<T> func)
    {
        Result = func.Invoke();
    }

    //If supporting only 2.0 use this and 
    //comment out the other overload
    public void ExecuteMethod(Delegate d)
    {
        Result = (T)d.DynamicInvoke();
    }
}

このコードを使用するには、Lambda(またはデリゲート)を使用できます。ラムダを使用した例を次に示します。

ThreadedMethod<bool> threadedMethod = new ThreadedMethod<bool>();
Thread workerThread = new Thread((unused) => 
                            threadedMethod.ExecuteMethod(() => 
                                SomeMethod()));
workerThread.Start();
workerThread.Join();
if (threadedMethod.Result == false) 
{
    //do something about it...
}

VB.NET 2008の実装


VB.NET 2008を使用しているユーザーは、値を返さないメソッドでラムダを使用できません。これはThreadedMethodクラスに影響を与えるのでExecuteMethod、関数の値を返します。これは何も傷つけません。

Public Class ThreadedMethod(Of T)

    Private mResult As T
    Public Property Result() As T
        Get
            Return mResult
        End Get
        Private Set(ByVal value As T)
            mResult = value
        End Set
    End Property

    Sub New()
    End Sub

    'If supporting .net 3.5'
    Function ExecuteMethod(ByVal func As Func(Of T)) As T
        Result = func.Invoke()
        Return Result
    End Function

    'If supporting only 2.0 use this and' 
    'comment out the other overload'
    Function ExecuteMethod(ByVal d As [Delegate]) As T
        Result = DirectCast(d.DynamicInvoke(), T)
        Return Result
    End Function

End Class

7

最新の.NET Frameworkでは、タスクを使用して別のスレッドから値を返すことが可能です。この場合、Resultプロパティは、タスクが完了するまで呼び出しスレッドをブロックします。

  Task<MyClass> task = Task<MyClass>.Factory.StartNew(() =>
  {
      string s = "my message";
      double d = 3.14159;
      return new MyClass { Name = s, Number = d };
  });
  MyClass test = task.Result;

詳細については、http://msdn.microsoft.com/en-us/library/dd537613(v = vs.110).aspxを参照してください


5

スレッドを開始するために使用されるC#のThreadStartデリゲートには、戻り型 'void'があります。

スレッドから「戻り値」を取得する場合は、共有の場所に(適切なスレッドセーフな方法で)書き込み、スレッドの実行が完了したときにその場所から読み取ります。


5

BackgroundWorkerを使用せず、通常のスレッドを使用する場合は、次のようにイベントを発生させてデータを返すことができます。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ThreadWithDataReturnExample
{
    public partial class Form1 : Form
    {
        private Thread thread1 = null;

        public Form1()
        {
            InitializeComponent();

            thread1 = new Thread(new ThreadStart(this.threadEntryPoint));
            Thread1Completed += new AsyncCompletedEventHandler(thread1_Thread1Completed);
        }

        private void startButton_Click(object sender, EventArgs e)
        {
            thread1.Start();
            //Alternatively, you could pass some object
            //in such as Start(someObject);
            //With apprioriate locking, or protocol where
            //no other threads access the object until
            //an event signals when the thread is complete,
            //any other class with a reference to the object 
            //would be able to access that data.
            //But instead, I'm going to use AsyncCompletedEventArgs 
            //in an event that signals completion
        }

        void thread1_Thread1Completed(object sender, AsyncCompletedEventArgs e)
        {
            if (this.InvokeRequired)
            {//marshal the call if we are not on the GUI thread                
                BeginInvoke(new AsyncCompletedEventHandler(thread1_Thread1Completed),
                  new object[] { sender, e });
            }
            else
            {
                //display error if error occurred
                //if no error occurred, process data
                if (e.Error == null)
                {//then success

                    MessageBox.Show("Worker thread completed successfully");
                    DataYouWantToReturn someData = e.UserState as DataYouWantToReturn;
                    MessageBox.Show("Your data my lord: " + someData.someProperty);

                }
                else//error
                {
                    MessageBox.Show("The following error occurred:" + Environment.NewLine + e.Error.ToString());
                }
            }
        }

        #region I would actually move all of this into it's own class
            private void threadEntryPoint()
            {
                //do a bunch of stuff

                //when you are done:
                //initialize object with data that you want to return
                DataYouWantToReturn dataYouWantToReturn = new DataYouWantToReturn();
                dataYouWantToReturn.someProperty = "more data";

                //signal completion by firing an event
                OnThread1Completed(new AsyncCompletedEventArgs(null, false, dataYouWantToReturn));
            }

            /// <summary>
            /// Occurs when processing has finished or an error occurred.
            /// </summary>
            public event AsyncCompletedEventHandler Thread1Completed;
            protected virtual void OnThread1Completed(AsyncCompletedEventArgs e)
            {
                //copy locally
                AsyncCompletedEventHandler handler = Thread1Completed;
                if (handler != null)
                {
                    handler(this, e);
                }
            }
        #endregion

    }
}

コードの細部を修正しました。AsyncCompletedEventHandlerのthread1_配線の部分を省略したようです。編集が間違っていた場合は、そこで何が起こっているのかを理解してください。
jp2code

1
jp2code @あなたは行うことができないthread1_Thread1Completed +=ので、thread1_Thread1Completedあなたが代入演算子の左側にそれを置くことができないので、関数の名前です。左側Thread1Completed +=が使用されるのはそれがイベントなので、イベントハンドラーを追加するために代入演算子の左側に表示される可能性があります。参照public event AsyncCompletedEventHandler Thread1Completed;
AaronLS

今見えます。#region以前にセクションでそのイベントハンドラーを表示できなかった理由がわかりません。私は見ました。正直!:)
jp2code

2

スレッドには実際には戻り値はありません。ただし、デリゲートを作成した場合は、BeginInvokeメソッドを介して非同期に呼び出すことができます。これにより、スレッドプールスレッドでメソッドが実行されます。などの呼び出しから戻り値を取得できますEndInvoke

例:

static int GetAnswer() {
   return 42;
}

...

Func<int> method = GetAnswer;
var res = method.BeginInvoke(null, null); // provide args as needed
var answer = method.EndInvoke(res);

GetAnswerスレッドプールスレッドで実行され、完了すると、EndInvoke図のように応答を取得できます。


2

BackgroundWorkerの Windowsフォーム用に開発する場合にいいです。

簡単なクラスをやり取りしたいとします。

class Anything {
    // Number and Text are for instructional purposes only
    public int Number { get; set; }
    public string Text { get; set; }
    // Data can be any object - even another class
    public object Data { get; set; }
}

私は次のことを行う短いクラスを書きました:

  • リストを作成またはクリアする
  • ループを開始する
  • ループで、リストの新しいアイテムを作成します
  • ループでスレッドを作成する
  • ループでは、アイテムをパラメーターとしてスレッドに送信します
  • ループで、スレッドを開始します
  • ループでは、監視するリストにスレッドを追加します
  • ループの後、各スレッドに参加します
  • すべての結合が完了したら、結果を表示します

スレッドルーチン内から:

  • 一度に1つのスレッドのみがこのルーチンに入ることができるようにロックを呼び出します(他のスレッドは待機する必要があります)
  • アイテムに関する情報を投稿します。
  • アイテムを変更します。
  • スレッドが完了すると、データがコンソールに表示されます。

デリゲートを追加すると、データをメインスレッドに直接ポストバックするのに役立ちますが、一部のデータアイテムがスレッドセーフでない場合は、Invokeを使用する必要があります。

class AnyTask {

    private object m_lock;

    public AnyTask() {
        m_lock = new object();
    }
    // Something to use the delegate
    public event MainDelegate OnUpdate;

    public void Test_Function(int count) {
        var list = new List<Thread>(count);
        for (var i = 0; i < count; i++) {
            var thread = new Thread(new ParameterizedThreadStart(Thread_Task));
            var item = new Anything() {
                Number = i,
                Text = String.Format("Test_Function #{0}", i)
            };
            thread.Start(item);
            list.Add(thread);
        }
        foreach (var thread in list) {
            thread.Join();
        }
    }

    private void MainUpdate(Anything item, bool original) {
        if (OnUpdate != null) {
            OnUpdate(item, original);
        }
    }

    private void Thread_Task(object parameter) {
        lock (m_lock) {
            var item = (Anything)parameter;
            MainUpdate(item, true);
            item.Text = String.Format("{0}; Thread_Task #{1}", item.Text, item.Number);
            item.Number = 0;
            MainUpdate(item, false);
        }
    }

}

これをテストするには、小さなコンソールアプリケーションを作成し、これをProgram.csファイルに入れます。

// A delegate makes life simpler
delegate void MainDelegate(Anything sender, bool original);

class Program {

    private const int COUNT = 15;
    private static List<Anything> m_list;

    static void Main(string[] args) {
        m_list = new List<Anything>(COUNT);
        var obj = new AnyTask();
        obj.OnUpdate += new MainDelegate(ThreadMessages);
        obj.Test_Function(COUNT);
        Console.WriteLine();
        foreach (var item in m_list) {
            Console.WriteLine("[Complete]:" + item.Text);
        }
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }

    private static void ThreadMessages(Anything item, bool original) {
        if (original) {
            Console.WriteLine("[main method]:" + item.Text);
        } else {
            m_list.Add(item);
        }
    }

}

これは私がこれで得たもののスクリーンショットです:

コンソール出力

私が説明しようとしたことを他の人が理解できることを願っています。

スレッドの作成とデリゲートの使用を楽しんでいます。C#をとても楽しいものにします。

付録:VB Codersの場合

上記のコードをVBコンソールアプリケーションとして記述する際に何が関係しているかを確認したいと思いました。変換には予想外のいくつかのことが含まれていたため、VBでスレッド化する方法を知りたい人のために、このスレッドをここで更新します。

Imports System.Threading

Delegate Sub MainDelegate(sender As Anything, original As Boolean)

Class Main

    Private Const COUNT As Integer = 15
    Private Shared m_list As List(Of Anything)

    Public Shared Sub Main(args As String())
        m_list = New List(Of Anything)(COUNT)
        Dim obj As New AnyTask()
        AddHandler obj.OnUpdate, New MainDelegate(AddressOf ThreadMessages)
        obj.Test_Function(COUNT)
        Console.WriteLine()
        For Each item As Anything In m_list
            Console.WriteLine("[Complete]:" + item.Text)
        Next
        Console.WriteLine("Press any key to exit.")
        Console.ReadKey()
    End Sub

    Private Shared Sub ThreadMessages(item As Anything, original As Boolean)
        If original Then
            Console.WriteLine("[main method]:" + item.Text)
        Else
            m_list.Add(item)
        End If
    End Sub

End Class

Class AnyTask

    Private m_lock As Object

    Public Sub New()
        m_lock = New Object()
    End Sub
    ' Something to use the delegate
    Public Event OnUpdate As MainDelegate

    Public Sub Test_Function(count As Integer)
        Dim list As New List(Of Thread)(count)
        For i As Int32 = 0 To count - 1
            Dim thread As New Thread(New ParameterizedThreadStart(AddressOf Thread_Task))
            Dim item As New Anything()
            item.Number = i
            item.Text = String.Format("Test_Function #{0}", i)
            thread.Start(item)
            list.Add(thread)
        Next
        For Each thread As Thread In list
            thread.Join()
        Next
    End Sub

    Private Sub MainUpdate(item As Anything, original As Boolean)
        RaiseEvent OnUpdate(item, original)
    End Sub

    Private Sub Thread_Task(parameter As Object)
        SyncLock m_lock
            Dim item As Anything = DirectCast(parameter, Anything)
            MainUpdate(item, True)
            item.Text = [String].Format("{0}; Thread_Task #{1}", item.Text, item.Number)
            item.Number = 0
            MainUpdate(item, False)
        End SyncLock
    End Sub

End Class


Class Anything
    ' Number and Text are for instructional purposes only
    Public Property Number() As Integer
        Get
            Return m_Number
        End Get
        Set(value As Integer)
            m_Number = value
        End Set
    End Property
    Private m_Number As Integer
    Public Property Text() As String
        Get
            Return m_Text
        End Get
        Set(value As String)
            m_Text = value
        End Set
    End Property
    Private m_Text As String
    ' Data can be anything or another class
    Public Property Data() As Object
        Get
            Return m_Data
        End Get
        Set(value As Object)
            m_Data = value
        End Set
    End Property
    Private m_Data As Object
End Class

1
class Program
{
    static void Main(string[] args)
    {
        string returnValue = null;
       new Thread(
          () =>
          {
              returnValue =test() ; 
          }).Start();
        Console.WriteLine(returnValue);
        Console.ReadKey();
    }

    public static string test()
    {
        return "Returning From Thread called method";
    }
}

提供されている例は間違っています。うまくいったのは幸運です。次の状況を想像してみてくださいtest(){ Thread.Sleep(5000); /*Highly time demanding process*/ return "Returned from test()";}。この場合、スタンドアロンスレッドは新しい値をreturnValue変数に割り当てる時間がありません。最後の手段として、スレッド参照var standaloneThread = new Thread(()=> //...);を保存し、その後、同期された方法で開始することができますstandaloneThread.Start(); standaloneThread.Join();。しかし、これは確かにベストプラクティスではありません。
AlexMelw 2017年

1

簡単な解決策は、スレッドで実行されている関数にrefによってパラメーターを渡し、その値をスレッドで変更することです。

       // create a list of threads
        List<Thread> threads = new List<Thread>();


        //declare the ref params
        bool is1 = false;
        bool is2 = false;

        threads.Add(new Thread(() => myFunction(someVar, ref is1)));
        threads.Add(new Thread(() => myFunction(someVar, ref is2)));

        threads.ForEach(x => x.Start());

        // wait for threads to finish
        threads.ForEach(x => x.Join());

        //check the ref params
        if (!is1)
        {
          //do something
        }

        if (!is2)
        {
           //do somethign else
        }

トレッドで実行されている関数を変更できない場合は、別の関数にラップできます。

 bool theirFunction(var someVar){
   return false;
}


 void myFunction(var someVar ref bool result){
  result = theirFunction(myVar);
 }

反対票について説明してください。私は自分のコードでこのパターンを使用しており、完全にうまく機能します。
CodeToad 14年

0

このコードを使用できます:

 private Object MyThread(Object Data)
      {
        Object response = null;
        Thread newThread = new Thread(() =>
        {
            response = MyFunction(Data);
            //MyFunction Is Function that you Define
        });
        newThread.Start();
        newThread.Join();
        return response;
      }

-1

私はスレッディングの専門家ではないので、次のようにしました。

設定ファイルを作成して

新しいスレッドの内部:

Setting.Default.ValueToBeSaved;
Setting.Default.Save();

次に、必要なときにその値を取得します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.