dispatch_async vs dispatch_sync获取数据。迅速

时间:2016-08-18 06:15:39

标签: swift concurrency fetch dispatch dispatch-async

在阅读了很多有关并行和并发的帖子之后,我仍然混淆了获取数据的正确方法。例如,在我的项目中,我有一个用户来获取数据的按钮。我的代码如下所示。

var array = [Int]()
func fetchData() {

   ....
   ....
   response(objects: [object], error: NSError?) {
       for object in objects {
           array.append(object.number) // assume object.number return an Int
       }

       // confuse here. Should I use async here because I am worry if the user 
       // click the fetchData button more than one time, the append and make 
       // function will be happened at the same time. Or, is there anything I 
       // made a wrong assumption? I guess I need a serial operation. Correct?

       dispatch_async(dispatch_get_main_queue()) {
           makeCollectionView() // using the data in array
       }
   }
}

更新

试图运行此代码。 10000-9999在0-9999之后运行。似乎第二个异步不会阻止第一个异步处理它的操作。

dispatch_async(dispatch_get_main_queue(), { () -> Void in
    for i in 0 ..< 10000 {
        print(i)
    }
})
dispatch_async(dispatch_get_main_queue(), { () -> Void in
    for i in 10000 ..< 20000 {
         print(i)
    }
})

2 个答案:

答案 0 :(得分:1)

为了提高性能,涉及UI的任何内容都应该在主线程上运行。所以基本上:

dispatch_async(dispatch_get_main_queue()) {
       //anything that involves UI
   }

答案 1 :(得分:0)

GCD提供执行任务的队列。队列可以有两种类型 - 并发串行。在串行队列任务中,每次执行一个(按FIFO顺序),在并发队列中执行多个任务。

为了防止用户在一次获取任务运行时获取数据,此时需要不将提取任务提交到队列。无论是什么类型的队列 - 并发或串行。

using System;
using System.Collections.Generic;
using System.Windows;
using System.IO.Ports;
using System.Text;

namespace MainApplication
{
    public partial class MainWindow : Window
    {
        private SerialConnectionHandler m_SerialConnectionHandler;

        public MainWindow()
        {
            InitializeComponent();
            m_SerialConnectionHandler = new SerialConnectionHandler();
            m_SerialConnectionHandler.ResponseReceived += SerialConnectionHandler_ResponseReceived;
        }

        private void SerialConnectionHandler_ResponseReceived(object sender, EventArgs e)
        {
            // Do something.
        }
    }

    public class SerialConnectionHandler
    {
        private List<SerialPort> m_SerialConnections;
        private List<SerialCommand> m_CommandQueue;
        private object m_DataReceivedLock;

        public event EventHandler ResponseReceived;

        public SerialConnectionHandler()
        {
            m_SerialConnections = new List<SerialPort>();
            m_CommandQueue = new List<SerialCommand>();
            m_DataReceivedLock = new object();

            foreach (var comPortName in SerialPort.GetPortNames())
            {
                var newSerialPort = new SerialPort(comPortName);
                newSerialPort.DataReceived += SerialPort_DataReceived;

                var newSerialCommand = new SerialCommand(comPortName, "Command", "Response");

                newSerialPort.Open();
                newSerialPort.Write(newSerialCommand.Command, 0, newSerialCommand.Command.Length);
                m_SerialConnections.Add(newSerialPort);
            }
        }

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            lock (m_DataReceivedLock)
            {
                var serialPort = (SerialPort)sender;

                var receivedContent = new byte[serialPort.BytesToRead];
                serialPort.Read(receivedContent, 0, receivedContent.Length);

                // Clear in buffer.
                serialPort.DiscardInBuffer();

                // Do something which could lead to problems if multiple com ports receive at the same time something.
                foreach (var command in m_CommandQueue.FindAll(command => command.SerialPortName.Equals(serialPort.PortName)))
                {
                    if (command.ExpectedResponse.Equals(receivedContent.ToString()))
                    {
                        ResponseReceived?.Invoke(this, new EventArgs());

                        m_CommandQueue.Remove(command);
                        break;
                    }
                }
            }
        }
    }

    public class SerialCommand
    {
        public string SerialPortName { get; }
        public byte[] Command { get; }
        public string ExpectedResponse { get; }

        public SerialCommand(string serialPortName, string command, string expectedResponse)
        {
            SerialPortName = serialPortName;
            Command = Encoding.ASCII.GetBytes(command);
            ExpectedResponse = expectedResponse;
        }
    }
}

var array = [Int]() var isFethingData = false func fetchData() { if !isFethingData { isFethingData = true dispatch_async(queueForFetchData) { … response(objects: [object], error: NSError?) { for object in objects { array.append(object.number) } dispatch_async(dispatch_get_main_queue()) { makeCollectionView() } isFethingData = false } } } dispatch_async是将任务提交到队列的函数。不同之处在于dispatch_sync在提交任务后立即返回,但dispatch_async等待任务完成。例如:

dispatch_sync