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