在F#中,我可以在一个线程上调用一个函数,但在另一个线程上返回吗?

时间:2020-12-16 20:56:09

I really want to be able to have a function pass some responsiblity to another object and then return on a different thread. I know this means the caller would not know that it had switched threads, but I REALLY want to know if there is ANY way to have the function return on a different thread than it was called on.

我真的希望能够让一个函数将一些责任传递给另一个对象,然后返回另一个线程。我知道这意味着调用者不会知道它已经切换了线程,但我真的想知道是否有任何方法让函数返回不同于调用它的线程。

3 个解决方案

#1


Async workflows give the illusion of something like this, e.g.

异步工作流程会产生类似这样的错觉,例如:

async {
    printfn "on thread 1..."
    let! r = stream.ReadAsync()
    printfn "on thread 2 now..."
    ...
}

but it's just an illusion to make the code easy to read, write, and reason about; under the hood it's doing all the normal async stuff with BeginRead/EndRead/callbacks/etc.

但是让代码易于阅读,编写和推理只是一种幻想;在引擎盖下,它正在使用BeginRead / EndRead / callbacks / etc执行所有正常的异步操作。

#2


You seem to have some misunderstanding of how threads work. You cannot enter a function in one thread and exit it in another (Threads have separate stacks and the stack maintains what function you are in). What you can do is use Asynchronous api's which invoke a function which returns immediately and allows retrival of the result later.

你似乎对线程如何工作有一些误解。您不能在一个线程中输入函数并在另一个线程中退出(线程具有单独的堆栈,并且堆栈会维护您所处的功能)。你可以做的是使用异步api,它调用一个立即返回的函数,并允许稍后重新生成结果。

Options include:

Returning some value which will allow querying of the state of the asynchronous operation ('are you done yet') and allowing retrieval of the result once it indicates it is done ('give the result') These will often allow usage on multiple threads.

返回一些值,允许查询异步操作的状态(“你还没完成”)并允许在结果指示完成后检索结果('给出结果')这些通常允许在多个线程上使用。

Providing a function to the original function which will be invoked later when the result finishes (often the thread on which this callback occurs is not well defined since it is likely to come from some thread pool.

为原始函数提供一个函数,该函数将在结果完成后调用(通常,发生此回调的线程没有很好地定义,因为它可能来自某个线程池。

Asynchronous api's are often complex.

异步api通常很复杂。

Something often required is for one function call to synchronously invoke some other function on a different thread. Common examples are smuggling some call onto the event loop dispatch thread (in windows by the Invoke() method).

通常需要的是一个函数调用同步调用另一个线程上的其他函数。常见的例子是将一些调用走私到事件循环调度线程(在窗口中通过Invoke()方法)。

It is possible that a system could provide a thread equivalent of fork() where by the entire thread is cloned (including the stack thus far) then both threads return from the function. This behaviour would likely be extremely bug prone.

系统可能提供相当于fork()的线程,其中整个线程被克隆(包括到目前为止的堆栈),然后两个线程从函数返回。这种行为可能极易出错。

Continuations may provide a controlled way to do what you are trying to achieve but they are very complex and may damage the readability of what you are trying to achieve.

延续可以提供一种可控制的方式来完成您想要实现的目标,但它们非常复杂并且可能会损害您尝试实现的可读性。

#3


Using .NET asynchronous delegates, you can pass an object to a function that executes on a separate thread, and have it execute a callback function when it's finished. That callback function will be called on a different thread than the main thread.

使用.NET异步委托,您可以将对象传递给在单独线程上执行的函数,并在完成后让它执行回调函数。该回调函数将在与主线程不同的线程上调用。

If you're familiar with C# or Visual Basic, you can find a lot of information about using asynchronous delegates in .NET. I haven't seen a good treatment of asynchronous delegates in F#.

如果您熟悉C#或Visual Basic,可以在.NET中找到有关使用异步委托的大量信息。我没有看到F#中异步委托的良好处理。

#1


Async workflows give the illusion of something like this, e.g.

异步工作流程会产生类似这样的错觉,例如:

async {
    printfn "on thread 1..."
    let! r = stream.ReadAsync()
    printfn "on thread 2 now..."
    ...
}

but it's just an illusion to make the code easy to read, write, and reason about; under the hood it's doing all the normal async stuff with BeginRead/EndRead/callbacks/etc.

但是让代码易于阅读,编写和推理只是一种幻想;在引擎盖下,它正在使用BeginRead / EndRead / callbacks / etc执行所有正常的异步操作。

#2


You seem to have some misunderstanding of how threads work. You cannot enter a function in one thread and exit it in another (Threads have separate stacks and the stack maintains what function you are in). What you can do is use Asynchronous api's which invoke a function which returns immediately and allows retrival of the result later.

你似乎对线程如何工作有一些误解。您不能在一个线程中输入函数并在另一个线程中退出(线程具有单独的堆栈,并且堆栈会维护您所处的功能)。你可以做的是使用异步api,它调用一个立即返回的函数,并允许稍后重新生成结果。

Options include:

Returning some value which will allow querying of the state of the asynchronous operation ('are you done yet') and allowing retrieval of the result once it indicates it is done ('give the result') These will often allow usage on multiple threads.

返回一些值,允许查询异步操作的状态(“你还没完成”)并允许在结果指示完成后检索结果('给出结果')这些通常允许在多个线程上使用。

Providing a function to the original function which will be invoked later when the result finishes (often the thread on which this callback occurs is not well defined since it is likely to come from some thread pool.

为原始函数提供一个函数,该函数将在结果完成后调用(通常,发生此回调的线程没有很好地定义,因为它可能来自某个线程池。

Asynchronous api's are often complex.

异步api通常很复杂。

Something often required is for one function call to synchronously invoke some other function on a different thread. Common examples are smuggling some call onto the event loop dispatch thread (in windows by the Invoke() method).

通常需要的是一个函数调用同步调用另一个线程上的其他函数。常见的例子是将一些调用走私到事件循环调度线程(在窗口中通过Invoke()方法)。

It is possible that a system could provide a thread equivalent of fork() where by the entire thread is cloned (including the stack thus far) then both threads return from the function. This behaviour would likely be extremely bug prone.

系统可能提供相当于fork()的线程,其中整个线程被克隆(包括到目前为止的堆栈),然后两个线程从函数返回。这种行为可能极易出错。

Continuations may provide a controlled way to do what you are trying to achieve but they are very complex and may damage the readability of what you are trying to achieve.

延续可以提供一种可控制的方式来完成您想要实现的目标,但它们非常复杂并且可能会损害您尝试实现的可读性。

#3


Using .NET asynchronous delegates, you can pass an object to a function that executes on a separate thread, and have it execute a callback function when it's finished. That callback function will be called on a different thread than the main thread.

使用.NET异步委托,您可以将对象传递给在单独线程上执行的函数,并在完成后让它执行回调函数。该回调函数将在与主线程不同的线程上调用。

If you're familiar with C# or Visual Basic, you can find a lot of information about using asynchronous delegates in .NET. I haven't seen a good treatment of asynchronous delegates in F#.

如果您熟悉C#或Visual Basic,可以在.NET中找到有关使用异步委托的大量信息。我没有看到F#中异步委托的良好处理。