我有一个完整列表,默认情况下,我使用concat / andThen运算符一个接一个地运行它们。 有时,我希望部分可完成对象并行运行,并且在完成所有操作后继续执行列表中的下一个可完成对象。 我试图通过以下代码实现这一目标:
var completable =
getAsyncCompletables()?.let {
it
} ?: run {
completables.removeAt(0).getCompletable()
}
while (completables.isNotEmpty()) {
val nextCompletable = getAsyncCompletables()?.let {
it
} ?: run {
completables.removeAt(0).getCompletable()
}
completable = nextCompletable.startWith(completable)
}
completable
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe()
我使用以下代码来检测异步可完成对象:
private fun getAsyncCompletables(): Completable? {
if (completables.size < 2 || !completables[1].async) {
return null
}
var completable = completables.removeAt(0).getCompletable()
while (completables.isNotEmpty() && completables[0].async) {
completable = completable.mergeWith(completables.removeAt(0).getCompletable())
}
return completable
}
所有工作正常,除了一件事,尽管我使用了“ startWith”,但最后一个可完成的操作没有触发。 我也尝试过“ concatWith”和“ andThen”,但结果相同。
答案 0 :(得分:1)
如果不看更多代码,特别是#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern size_t read_line(FILE *file, char **line);
typedef enum Category {
OBJECT, DESCRIPTION, TYPE
} Category;
Category next_category(const Category category)
{
return (Category) ((category + 1) % 3);
}
int main(void)
{
char *object[3];
char *description[3];
char *type[3];
size_t counter = 0;
FILE *file = fopen("example.csv", "r");
char *line = NULL;
size_t length = 0;
while ((length = read_line(file, &line)) > 0 && counter < sizeof(object)) {
Category token_category = 0;
char *next_token = strtok(line, ";");
while (next_token != NULL) {
size_t token_length = strlen(next_token);
switch (token_category) {
case OBJECT:
object[counter] = calloc(token_length, sizeof(char));
memcpy(object[counter], next_token, token_length);
break;
case DESCRIPTION:
description[counter] = calloc(token_length, sizeof(char));
memcpy(description[counter], next_token, token_length);
break;
case TYPE:
type[counter] = calloc(token_length, sizeof(char));
memcpy(type[counter], next_token, token_length);
break;
}
// Read the next token from the same string
next_token = strtok(NULL, ";");
token_category = next_category(token_category);
}
free(next_token);
free(line);
++counter;
}
fclose(file);
printf("Objects: %s, %s, %s\n", object[0], object[1], object[2]);
printf("Descriptions: %s, %s, %s\n", description[0], description[1], description[2]);
printf("Types: %s, %s, %s\n", type[0], type[1], type[2]);
return 0;
}
的工作以及async
的数据结构是什么,很难回答。但是,无论这些值如何,您正在寻找的答案很可能都是相似的。您可能要使用completables
或Completable.merge(...)
。
根据文档:
Completable.mergeArray(...)
为了实现并行执行,您将需要使用新线程调用列表/数组/集中的 /**
* Returns a Completable instance that subscribes to all sources at once and
* completes only when all source Completables complete or one of them emits an error.
* ...
*/
的每个Completable。可以使用subscribeOn
或通过Schedulers.newThread()
之类的共享池来完成。
为了确定,我进行了测试。这是代码。
Schedulers.io()
这是输出。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
val completeOne = Completable.fromAction {
Timber.d("Completable #1 running on ${Thread.currentThread().name}")
}
val completeTwo = Completable.fromAction {
Timber.d("Completable #2 running on ${Thread.currentThread().name}")
}
val completeThree = Completable.fromAction {
Timber.d("Completable #3 running on ${Thread.currentThread().name}")
}
val completables = listOf(completeOne, completeTwo, completeThree).map { CompletableWrapper(it) }
val asyncCompletables = completables
.asSequence()
.filter { it.async }
.map { it.getCompletable().subscribeOn(Schedulers.io()) }
.toList()
Completable.merge(asyncCompletables)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
Timber.i("Completed all completables")
}, Timber::e)
}
class CompletableWrapper(
private val completable: Completable,
val async: Boolean = true
) {
fun getCompletable() = completable
}
如您所见,它将在池中的新线程上运行每个可完成对象,并且仅在每个可完成对象完成之后才调用全部完成的操作。
See here for the documentation on Completable.merge/mergeArray。