我有一个异步函数,我想连续多次调用。 问题是"多个"可能是几十万或几百万...
显而易见的方法是从回调中调用相同的函数:
function foo()
{
asyncBar(foo);
}
当然有一些逻辑可以阻止递归。问题是堆栈是否正在填充调用,并且可能在某个时刻导致堆栈溢出?
答案 0 :(得分:9)
问题是堆栈是否正在填充调用并可能导致 stackoverflow在某个时刻?
否。如果JNIEXPORT void JNICALL Java_com_example_photoprocessing_activity_SurfaceProcessingActivity_showJPG(
JNIEnv * env, jobject activity, jobject surface, jstring img) {
const char * imgChar;
jboolean * isCopy;
imgChar = env->GetStringUTFChars(img, 0);
ANativeWindow_Buffer nwBuffer;
LOGI("img path : %s ",imgChar);
LOGI("ANativeWindow_fromSurface ");
ANativeWindow * mANativeWindow = ANativeWindow_fromSurface(env, surface);
if (mANativeWindow == NULL) {
LOGE("ANativeWindow_fromSurface error");
return;
}
LOGI("ANativeWindow_lock ");
if (0 != ANativeWindow_lock(mANativeWindow, &nwBuffer, 0)) {
LOGE("ANativeWindow_lock error");
return;
}
read_jpeg_file_show(imgChar, nwBuffer);
if (nwBuffer.format == WINDOW_FORMAT_RGBA_8888) {
LOGI("nwBuffer->format == WINDOW_FORMAT_RGBA_8888 ");
}
LOGI("ANativeWindow_unlockAndPost ");
if (0 != ANativeWindow_unlockAndPost(mANativeWindow)) {
LOGE("ANativeWindow_unlockAndPost error");
return;
}
env->ReleaseStringUTFChars(img,imgChar);
ANativeWindow_release(mANativeWindow);
LOGI("ANativeWindow_release ");
return;
}
int read_jpeg_file_show(const char *input_filename,
ANativeWindow_Buffer& nwBuffer) {
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *input_file;
JSAMPARRAY buffer;
int row_width;
unsigned char *buffertmp;
cinfo.err = jpeg_std_error(&jerr);
if ((input_file = fopen(input_filename, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", input_filename);
LOGI("can't open jpg1");
return -1;
}
jpeg_create_decompress(&cinfo);
/* Specify data source for decompression */
jpeg_stdio_src(&cinfo, input_file);
/* Read file header, set default decompression parameters */
(void) jpeg_read_header(&cinfo, TRUE);
/* Start decompressor */
(void) jpeg_start_decompress(&cinfo);
row_width = cinfo.output_width * cinfo.output_components;
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE,
row_width, 1);
buffertmp = (unsigned char *) malloc(row_width);
memset(buffertmp, 0, row_width);
LOGI("malloc and memset");
/* Process data */
int get8h5 = 248, get8h6 = 252;
__uint16_t * line = (__uint16_t *) nwBuffer.bits;
int wheight = 0;
int scalew = 1, scaleh = 1;
if (cinfo.output_width > nwBuffer.width) {
scalew = cinfo.output_width / nwBuffer.width;
}
LOGI(" scale of img = %d", scalew);
for (int i = 0, choosehNum = 0; i < cinfo.output_height; i++) {
jpeg_read_scanlines(&cinfo, buffer, 1);
buffertmp = *buffer;
if (i % scalew == 0 && choosehNum++ < nwBuffer.height) {
//LOGI("nwBuffer->format == WINDOW_FORMAT_RGB_565");
for (int j = 0, choosewNum = 0; j < cinfo.output_width; j++) {
if (j % scalew == 0) {
if (nwBuffer.format == WINDOW_FORMAT_RGB_565) {
line[choosewNum] = ((__uint16_t ) buffertmp[3 * j + 0]
& get8h5) << 8
| ((__uint16_t ) (buffertmp[3 * j + 1] & get8h6)
<< 3)
| ((__uint16_t ) (buffertmp[3 * j + 2] & get8h6)
>> 3);
choosewNum++;
}
}
}
line = line + nwBuffer.stride;
}
}
(void) jpeg_finish_decompress(&cinfo);
LOGI("jpeg_finish_decompress !!");
jpeg_destroy_decompress(&cinfo);
LOGI("jpeg_destroy_decompress !!");
/* Close files, if we opened them */
fclose(input_file);
return 0;
}
调用回调,它会异步传递,那么就没有堆栈构建。
在您的代码中:
asyncBar()
这是正在发生的事情,一步一步:
function foo() {
asyncBar(foo);
}
。foo()
。asyncBar(foo)
是异步的,这意味着它启动了异步操作(假设它是一个http GET,但任何异步操作都可以)。启动异步操作,然后asyncBar
立即返回。asyncBar()
的初始调用返回并且堆栈完全解除。堆栈上不再有foo()
。foo()
后的任何代码都会继续运行,直到完成并返回事件循环。foo()
,因此它会调用该函数并重新开始循环,直到第2步。没有堆叠堆积。关键是异步回调在当前堆栈完成后被调用,解除并返回系统。
答案 1 :(得分:1)
问题是堆栈是否正在填充调用并可能导致 stackoverflow在某个时刻?
如果该方法是异步的,那么您根本不会获得 stackoverflow 。
请查看以下示例
function f1(n)
{
if (n > 0 )
{
callAsynch(n, function(n){
f1(n-1)
});
}
}
这个callAsynch
可能是一个Ajax调用(或任何异步的调用),它将回调方法作为参数。
它不会在堆栈上起作用,因为每次调用都以调用asynch方法结束,该方法不会将值返回给此方法,而是简单地将任务(调用f1(n-1)
)附加到队列之后完了。
答案 2 :(得分:0)
异步调用时无堆栈溢出。
也,
您可以在方法link期间使用 async 模块的来递归调用异步函数。