3

次のコードがあります。2秒以内にスレッドが終了しない場合はスレッドを中止します。最初のコードから、whileループで新しいmyThread evertyimeを作成し、それを中止しないことがわかります。まあ、私はそれをこのようにしたくありませんが、myThreadをループの外に出して、2番目のコードのようにabort()関数を使用する場合。中止するとエラーが発生します。

while (true)
        {

            try
            {
                m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//reset up socket
                myThread = new System.Threading.Thread(new System.Threading.ThreadStart(socket_connect));
                myThread.Start();
                if (!myThread.Join(2000))
                {
                    throw new SocketException(SocketError.AccessDenied);
                }

            }
            catch (Exception ex)
            {
                m_socket.Close();
            }
        }
    }
     private static void socket_connect()
    {
        m_socket.Connect(remoteEndPoint);//Connect to remote device  
    }

私は最初に次のコードを試していましたが、threadabortexceptionsが発生します。

 myThread = new System.Threading.Thread(new System.Threading.ThreadStart(socket_connect));   
  while (true)
        { try
            {
                m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream,     ProtocolType.Tcp);//reset up socket

                myThread.Start();
                if (!myThread.Join(2000))
                {

                    myThread.Abort();
                    throw new SocketException(SocketError.AccessDenied);
                }
            }
            catch (Exception ex)
            {
                m_socket.Close();
            }
        }
    }
    private static void socket_connect()
    {
        m_socket.Connect(remoteEndPoint);//Connect to remote device  
    }

abort()は良い考えではないことを知っているので、スレッドをそのままにして、C#(。Net?実際に誰がそれを行うのかわかりません)にガベージコレクションを処理させます。そして、このプログラムはスレッドの束を保持するためのメモリがあまりないボード上で実行されるので、誰でもそれが良い考えであるかどうかを知ることができます。そして、誰かがC#でガベージコレクションがどのように正確に行われるか教えてもらえますか?たとえば、スレッド。
もう1つ言及する必要があるのは、Taskクラスまたはsocket.beginconnect()メソッドがないことです。これは、PCではなく小さなボードで実行されるプログラムを作成しているためだと思います。ボードはnetduidoplusであり、netduinoplusプラットフォームでプロジェクトを構築しています。

4

2 に答える 2

1

次のコードがあります。スレッドが 2 秒以内に終了しない場合はスレッドを中止します。

コードを読むと、実際には 2 秒以内にソケットをリソースに接続しようとしているように見えます。2 秒以上経過した場合は、先に進みます。

私は主にこの回答のコードを再現しています。これは、スレッドをスピンアップして中止するのではなく、目標を達成するために行うべきことだと思います。

Socket socket = new Socket(AddressFamily.InterNetwork,
                           SocketType.Stream,
                           ProtocolType.Tcp);

// Connect using a timeout (2 seconds)

IAsyncResult result = socket.BeginConnect( sIP, iPort, null, null );

bool success = result.AsyncWaitHandle.WaitOne( 2000, true );

if ( !success )
{
            // NOTE, MUST CLOSE THE SOCKET

            socket.Close();
            throw new ApplicationException("Failed to connect server.");
}

// Success
//... 
于 2013-01-31T03:54:00.473 に答える
-1

[編集: タブを外す/間隔を空けると大量のコピーパスタが失敗する]

ライブラリを使用してくださいTask。これらの状況に対処する方がはるかに簡単です。

(LINQPad に適した BLOB)

void Main()
{
    var canceller = new CancellationTokenSource();
    var task = Task.Factory.StartNew(() => DoStuff(canceller.Token), canceller.Token);        
    if(!task.Wait(2000, canceller.Token))
    {
        canceller.Cancel();
        task.Wait(2);
    }
    sw.Elapsed.Dump();
}
private Stopwatch sw;
private void DoStuff(CancellationToken token)
{
    try
    {
        sw = Stopwatch.StartNew();
        while(!token.IsCancellationRequested)
        {       
        }
    }
    // no catch - rethrown exceptions must be checked on Task
    finally
    {
        sw.Stop();
    }
}

または、「終了フラグ」条件を使用できます。これは、スレッドスターターとスレッドランナーの両方が表示/変更できるブール値であり、それをwhile条件で使用します。

于 2013-01-31T02:29:57.793 に答える