teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

コード追加

2021/08/21 19:17

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -2,4 +2,87 @@
2
2
 
3
3
  cancel(true) とすると, AsyncTask 上で Thread.interrupted() が呼ばれたと思います。
4
4
 
5
- Thread.interrupted() で socket.receive() に割り込みが掛からないのであれば、 socket を close() してしまえば良いのではないでしょうか。(例外が発生するはずです。)
5
+ Thread.interrupted() で socket.receive() に割り込みが掛からないのであれば、 socket を close() してしまえば良いのではないでしょうか。(例外が発生するはずです。)
6
+
7
+ ----
8
+
9
+ 「停止用のダミーパケットを送り着ける」方法で停止させてみました。
10
+ レイアウトに Button(id=stopButton) があるとしまして、実行後ログに"レシーバの処理を開始" が出たのを確認してからボタンを押すと、"レシーバの処理を中断" が出ると思います。
11
+ (ダミーパケットの内容はテキトウです。)
12
+
13
+ MainActivity.java
14
+ ```java
15
+ import androidx.appcompat.app.AppCompatActivity;
16
+
17
+ import android.content.Context;
18
+ import android.os.*;
19
+ import android.util.Log;
20
+ import android.widget.Button;
21
+
22
+ import java.io.IOException;
23
+ import java.net.*;
24
+
25
+ public class MainActivity extends AppCompatActivity {
26
+
27
+ @Override
28
+ protected void onCreate(Bundle savedInstanceState) {
29
+ super.onCreate(savedInstanceState);
30
+ setContentView(R.layout.activity_main);
31
+
32
+ ReceiveTask receiveTask = new ReceiveTask(this);
33
+ receiveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
34
+
35
+ Button button = findViewById(R.id.stopButton);
36
+ button.setOnClickListener(view -> {
37
+ receiveTask.cancel(false);
38
+ new Thread(()->{
39
+ try(DatagramSocket s = new DatagramSocket();) {
40
+ DatagramPacket p = new DatagramPacket(new byte[]{0}, 1, InetAddress.getLocalHost(), socket.getLocalPort());
41
+ s.send(p);
42
+ } catch(IOException e) {
43
+ e.printStackTrace();
44
+ }
45
+ }).start();
46
+ });
47
+ }
48
+
49
+ private DatagramSocket socket;
50
+
51
+ class ReceiveTask extends AsyncTask<Void, Void, Void> {
52
+ private boolean running = true;
53
+
54
+ ReceiveTask(Context context) {
55
+ try {
56
+ socket = new DatagramSocket(33333);
57
+ } catch(SocketException e) {
58
+ e.printStackTrace();
59
+ }
60
+ }
61
+
62
+ @Override
63
+ protected Void doInBackground(Void... strings) {
64
+ DatagramPacket receivePacket = new DatagramPacket(new byte[2048], 2048);
65
+ Log.d("ReceiveTask", "レシーバの処理を開始");
66
+ while(running) {
67
+ if (isCancelled()){
68
+ Log.d("ReceiveTask", "isCancelled:レシーバの処理を中断します");
69
+ break;
70
+ }
71
+ try {
72
+ socket.receive(receivePacket);
73
+ } catch (IOException e) {
74
+ Log.d("ReceiveTask", "受信エラー:" + e);
75
+ }
76
+ }
77
+ Log.d("ReceiveTask", "レシーバの処理を中断");
78
+ return null;
79
+ }
80
+
81
+ @Override
82
+ protected void onCancelled() {
83
+ Log.d("ReceiveTask", "onCancelled:レシーバの処理を中断します");
84
+ running = false;
85
+ }
86
+ }
87
+ }
88
+ ```

2

追加

2021/08/21 19:17

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -1,3 +1,5 @@
1
- いくらフラグを操作した所で、socket.receive が戻ってこなければ何にもなりません。
1
+ いくらフラグを操作した所で、socket.receive() が戻ってこなければ何にもなりません。
2
2
 
3
- cancel(true) とすると, AsyncTask 上で Thread.interrupted() が呼ばれたと思います。
3
+ cancel(true) とすると, AsyncTask 上で Thread.interrupted() が呼ばれたと思います。
4
+
5
+ Thread.interrupted() で socket.receive() に割り込みが掛からないのであれば、 socket を close() してしまえば良いのではないでしょうか。(例外が発生するはずです。)

1

追加

2021/08/20 17:48

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -1,1 +1,3 @@
1
- いくらフラグを操作した所で、socket.receive が戻ってこなければ何にもなりません。
1
+ いくらフラグを操作した所で、socket.receive が戻ってこなければ何にもなりません。
2
+
3
+ cancel(true) とすると, AsyncTask 上で Thread.interrupted() が呼ばれたと思います。