Multithreading 向中间工作进程发送消息时,工作进程未完成

Multithreading 向中间工作进程发送消息时,工作进程未完成,multithreading,concurrency,d,Multithreading,Concurrency,D,我用“D语言编程”来学习D语言。我编写了一个简单的程序,生成一个worker,并向它发送一个数字以接收作为字符串的平方。worker 1获取数字平方,并将其发送给worker 2(一个不同的函数),以将其转换为字符串,该字符串返回给worker 1,从而将其返回给主函数调用。我可以用一根线把整件事写下来。我写它是为了更好地了解工人。我使用receive让worker 1根据输入进行操作。节目如下 import std.stdio; import std.concurrency; import s

我用“D语言编程”来学习D语言。我编写了一个简单的程序,生成一个worker,并向它发送一个数字以接收作为字符串的平方。worker 1获取数字平方,并将其发送给worker 2(一个不同的函数),以将其转换为字符串,该字符串返回给worker 1,从而将其返回给主函数调用。我可以用一根线把整件事写下来。我写它是为了更好地了解工人。我使用
receive
让worker 1根据输入进行操作。节目如下

import std.stdio;
import std.concurrency;
import std.conv;
import core.thread;

void main() {

  foreach (int num; 1..100) {
    auto square_tid = spawn(&square);
    square_tid.send(num);
    auto square = receiveOnly!string();
    writeln(square);
  }
}


void square() {
  static i = 0;
  receive (
       (int num) {
         auto square = num * num;
         writeln("sqaure : Comes in with " , num , " for " , ++i , " time");
         auto stringWorker = spawn(&stringConverter);
         stringWorker.send(thisTid, square, ownerTid);
       },
       (Tid tid, string str) {
         writeln("comes in string");
         send(tid, "hello");
       });
}

void stringConverter() {
  static i = 0;
  auto params = receiveOnly!(Tid, int, Tid)();
  auto stringified = to!string(params[1]); // Stringify the square
  writeln("string : Comes in with " , params[1], " for " , ++i , " time");
  params[0].send(params[2], stringified); // params[0] - square function tid, params[2] - main function tid
}
我可以接收主函数tid并直接将字符串发送回。但当我回到worker 1时,它被击中,不再继续。如何使线程接收主线程和从线程的输入。关于线程的另外几个问题:

  • 如果我想在不退出的情况下将-1作为数据发送给我的工作者。我怎么做
  • 在整个流程中使用一个worker可以吗?或者我可以像在foreach循环中那样使用多个worker
  • 本书使用以下代码。为什么它的值>=0在代码中很明显

如果我在任何术语上有错误,请纠正我

对于这种任务,最好使用std.parallelism

import std.stdio;
import std.parallelism;

void main() {
    auto squares = new long[100];
    foreach(i, ref elem; parallel(squares)) {
        elem = i * i;
    }

    writeln(squares);
}
并且将-1发送到工作线程也没有问题,它不会仅在显式请求时退出线程

以下是您尝试的修改版本:

import std.stdio;
import std.concurrency;
import std.conv;

void main() {

    foreach (int num; 1..100) {
        auto square_tid = spawn(&square);
        square_tid.send(num);
        auto square = receiveOnly!string();
        writeln(square);
    }
}


void square() {
    static shared i = 0;
    receive (
        (int num) {
        int square = num * num;
        writeln("sqaure : Comes in with " , num , " for " , ++i , " time");
        auto stringWorker = spawn(&stringConverter);
        stringWorker.send(thisTid, square, ownerTid);
        receive ((Tid tid, string str) { writeln("comes in string"); send(tid, "hello");});
    });
}

void stringConverter() {
    static shared i = 0;
    auto params = receiveOnly!(Tid, int, Tid)();
    auto stringified = to!string(params[1]); // Stringify the square
    writeln("string : Comes in with " , params[1], " for " , ++i , " time");
    params[0].send(params[2], stringified); // params[0] - square function tid, params[2] - main function tid
}
更新说明

代码中的
square
函数在
receive
之后结束。因此,它永远不会使用
(Tid-Tid,string-str)
部分尝试下一个块。这就是为什么我把它放在
receive
的第一部分

每次调用
spawn
都会创建新线程。由于默认情况下D使用TLS,
static
关键字在您的示例中是无用的。因为在每个新线程中,
i
都是
0
。这就是我使用
shared
关键字的原因

更新2

以下是一个版本,它可以解释更多事情是如何运作的:

import std.stdio;
import std.concurrency;
import std.conv;

void main() {

    foreach (int num; 1..100) {
        auto square_tid = spawn(&square);
        square_tid.send(num);
        auto square = receiveOnly!string();
        writeln(square);
    }
}


void square() {
    shared static i = 0;
    bool end = false;
    while(!end) receive (
        (int num) {
        auto square = num * num;
        writeln("sqaure : Comes in with " , num , " for " , ++i , " time");
        auto stringWorker = spawn(&stringConverter);
        stringWorker.send(square);
    },
    (string str) {
        writeln("comes in string");
        ownerTid.send(str);
        end = true;
    });
}

void stringConverter() {
    shared static i = 0;
    auto params = receiveOnly!(int)();
    auto stringified = to!string(params); // Stringify the square
    writeln("string : Comes in with " , params, " for " , ++i , " time");
    ownerTid.send(stringified); // params[0] - square function tid, params[2] - main function tid
}

谢谢我可以使用parallel,只是想了解线程之间的消息传递:)你能解释一下为什么用tid和int中的string包装receive调用会起作用吗。为什么要让我分享,因为它们是函数的独立静态变量。如果你想了解一些东西,那么它是提问的理想场所。我将编辑我的答案,解释为什么我要添加shared,以及为什么需要将它放在recive call中
import std.stdio;
import std.concurrency;
import std.conv;

void main() {

    foreach (int num; 1..100) {
        auto square_tid = spawn(&square);
        square_tid.send(num);
        auto square = receiveOnly!string();
        writeln(square);
    }
}


void square() {
    shared static i = 0;
    bool end = false;
    while(!end) receive (
        (int num) {
        auto square = num * num;
        writeln("sqaure : Comes in with " , num , " for " , ++i , " time");
        auto stringWorker = spawn(&stringConverter);
        stringWorker.send(square);
    },
    (string str) {
        writeln("comes in string");
        ownerTid.send(str);
        end = true;
    });
}

void stringConverter() {
    shared static i = 0;
    auto params = receiveOnly!(int)();
    auto stringified = to!string(params); // Stringify the square
    writeln("string : Comes in with " , params, " for " , ++i , " time");
    ownerTid.send(stringified); // params[0] - square function tid, params[2] - main function tid
}