获取FFT结果时应用程序挂起

时间:2016-08-10 06:42:39

标签: c# .net multithreading

我在FFTCalculated事件中有一个循环,它从FFT应用到原始数据后得到复数值。

基类

 private void FftCalculated(object sender, FftEventArgs e)
    {
        writer = new FFTWriter(path);
            foreach (var a in e.Result)
                writer.WriteValues(a.X,a.Y);  
    }

因为它在UI线程中我想将它移动到后台线程。所以我创建了一个并发队列并将两个值排入队列X和Y,并将它们写入文本文件。

 private ConcurrentQueue<Tuple<double?, double?>> _queue = new ConcurrentQueue<Tuple<double?,double?>>();
    private string _filePath;
    private Thread _workerThread;
    private bool _isDisposed;

    private void DoWork()
    {
        while (!_isDisposed)
        {
            Tuple<double?, double?> values;
            if (_queue != null && _queue.TryDequeue(out values))
            {
                if(File.Exists(_filePath))
                    try
                    {
                        File.AppendAllText(_filePath, values.Item1 + "," + values.Item2);
                    }
                    catch (Exception ex) { ex.ToString(); }
            }
        }
    }

    public void Dispose()
    {
        if (!_isDisposed)
        {
            _isDisposed = true;
            _workerThread.Join();
        }
    }

    public FFTWriter(string filePath)
    {
        _filePath = filePath;
        _workerThread = new Thread(DoWork);
        _workerThread.Start();
    }

    public void WriteValues(double? v1, double? v2)
    {
        if (v1.HasValue == true && v2.HasValue == true)
        _queue.Enqueue(new Tuple<double?,double?>(v1.Value, v2.Value));
    }

但是,应用程序仍然挂起。我做错了什么?我认为问题出在这里是因为循环在主线程中运行。我该如何解决这个问题?

 foreach (var a in e.Result)
                writer.WriteValues(a.X,a.Y);

1 个答案:

答案 0 :(得分:0)

从评论中将所有内容放在一起,您的代码应如下所示:

使用FFTWriter的代码:

private FFTWriter _writer;
private void StartNewFFT()
{
    _writer = new FFTWriter(path);
} 

private void FftCalculated(object sender, FftEventArgs e)
{
    _writer.WriteValues(e.Result);  
}

FFTWriter类中的代码

private BlockingCollection<IEnumerable<FFTResult>> _queue = new BlockingCollection<IEnumerable<FFTResult>>();
private string _filePath;
private Thread _workerThread;
private bool _isDisposed;

private void DoWork()
{
    if(_queue == null)
        return;

    if(!File.Exists(_filePath))
        return;

    using(var file = File.Open(_filePath))
    {
        foreach(var results in _queue)
        {
           try
           {
               foreach(var values in results)
               {
                   if (values.X.HasValue == true && values.Y.HasValue == true)
                       file.WriteLine($"{values.X},{values.Y}");
               }
           }
            catch (Exception ex) { ex.ToString(); }
           }
        }
    }
}

public void Dispose()
{
    if (!_isDisposed)
    {
        _queue.CompleteAdding();
        _isDisposed = true;
        _workerThread.Join();
    }
}

public FFTWriter(string filePath)
{
    _filePath = filePath;
    _workerThread = new Thread(DoWork);
    _workerThread.Start();
}

public void WriteValues(IEnumerable<FFTResult> results)
{
    _queue.Add(new Tuple<double?,double?>(v1.Value, v2.Value));
}

编辑:我将代码更改为仅使用FFTWriter的一个实例,并将外部foreach从使用代码移动到DoWork()方法中,以便在工作线程中执行。