2012-01-19 54 views
1

如何使用Timer类和Timer事件将此循环变成一次执行块的循环? 我刚刚运行循环的方法让冻结了flash/air用户界面。用定时器代替While()循环以防止GUI冻结[多线程?]

我正在尝试psuedo多线程。是的,这是从wavwriter.as:

// Write to file in chunks of converted data. 
    while (dataInput.bytesAvailable > 0) 
    { 
     tempData.clear(); 
     // Resampling logic variables 
     var minSamples:int = Math.min(dataInput.bytesAvailable/4, 8192); 
     var readSampleLength:int = minSamples;//Math.floor(minSamples/soundRate); 
     var resampleFrequency:int = 100; // Every X frames drop or add frames 
     var resampleFrequencyCheck:int = (soundRate-Math.floor(soundRate))*resampleFrequency; 
     var soundRateCeil:int = Math.ceil(soundRate); 
     var soundRateFloor:int = Math.floor(soundRate); 
     var jlen:int = 0; 
     var channelCount:int = (numOfChannels-inputNumChannels); 
     /* 
     trace("resampleFrequency: " + resampleFrequency + " resampleFrequencyCheck: " + resampleFrequencyCheck 
      + " soundRateCeil: " + soundRateCeil + " soundRateFloor: " + soundRateFloor); 
     */ 
     var value:Number = 0; 
     // Assumes data is in samples of float value 
     for (var i:int = 0;i < readSampleLength;i+=4) 
     { 
      value = dataInput.readFloat(); 
      // Check for sanity of float value 
      if (value > 1 || value < -1) 
       throw new Error("Audio samples not in float format"); 

      // Special case with 8bit WAV files 
      if (sampleBitRate == 8) 
       value = (bitResolution * value) + bitResolution; 
      else 
       value = bitResolution * value; 

      // Resampling Logic for non-integer sampling rate conversions 
      jlen = (resampleFrequencyCheck > 0 && i % resampleFrequency < resampleFrequencyCheck) ? soundRateCeil : soundRateFloor; 
      for (var j:int = 0; j < jlen; j++) 
      { 
       writeCorrectBits(tempData, value, channelCount); 
      } 
     } 
     dataOutput.writeBytes(tempData); 
    } 
} 
+0

为什么你不能只是添加计时器一些延迟? –

+0

因为它会尝试仍然使用录制音频的整个ByteArray。我需要一种方法来将dataInput分成几块字节...... – crzter

+0

你能给我整个calss代码来使你的代码得到很好的支持以给出适当的解决方案吗?我有想法,并且我实施了很多次这些事情。 – Mrugesh

回答

0

我曾经实施伪多线程在AS3由分解任务成块,而不是数据分割成块。

我的解决方案可能不是最优的,但它在执行大型深度优先搜索的同时允许Flash游戏良好地流动,对我来说效果很好。

  • 使用可变计数计算“滴答”,类似于CPU时钟周期。每次执行某个操作时,都会将此计数器增加1.在执行较重的操作后,将其增加更多。
  • 在代码中的特定部分,插入检查点在那里你是否>门槛,其中门槛是要优化参数你有这样的伪多线程工作后。
  • 如果在检查点的ticks> threshold,您保存任务的当前状态,将ticks设置为零,然后退出该功能。
  • 该方法必须稍后重试,因此您在这里使用的定时器的间隔参数也应稍后调整。
  • 重新启动该方法时,使用已暂停任务的已保存状态来检测应该恢复任务的位置。

为了您的具体情况,我建议拆分的任务循环,而不是想着while循环。这个想法是打断for循环,记住它们的状态,然后在休息间隔后继续。

为了简化,假设我们只有最外面的for循环。新方法的素描是:

WhileLoop: while (dataInput.bytesAvailable > 0 && ticks < threshold) 
{ 
    if(!didSubTaskA) { 
    // do subtask A... 
    ticks += 2; 
    didSubTaskA = true; 
    } 

    if(ticks > threshold) { 
    ticks = 0; 
    restTimer.reset(); 
    restTimer.start(); // This dispatches an event that should trigger this method 
    break WhileLoop; 
    } 

    for (var i:int = next_unused_i;i < readSampleLength;i+=4) { 
    next_unused_i = i+1; 
    // do subtask B... 
    ticks += 1; 
    if(ticks > threshold) { 
     ticks = 0; 
     restTimer.reset(); 
     restTimer.start(); 
     break WhileLoop; 
    } 
    } 

    next_unused_i = 0; 
    didSubTaskA = false; 
} 
if(ticks > threshold) { 
    ticks = 0; 
    restTimer.reset(); 
    restTimer.start(); 
} 

的变量,门槛restTimernext_unused_i,并didSubTaskA是重要的,而不能是局部的方法变量。它们可以是静态或类变量。子任务A是您“重新采样逻辑变量”的部分,以及那里使用的变量不能是局部变量,因此也要使它们成为类变量,因此当您离开并返回该方法时,它们的值可以保持不变。

您可以通过创建自己的Task类来使它看起来更好看,然后在那里存储“线程”算法的中断状态的整个状态。此外,你也许可以使检查点成为本地功能。

我没有测试上面的代码,所以我不能保证它的工作原理,但这个想法基本上是这样。我希望它可以帮助