Objective c 从Obj-C中的单独线程监视ifstream读取进度
这是我使用GCD在后台编写和读取文件的代码Objective c 从Obj-C中的单独线程监视ifstream读取进度,objective-c,multithreading,grand-central-dispatch,ifstream,Objective C,Multithreading,Grand Central Dispatch,Ifstream,这是我使用GCD在后台编写和读取文件的代码 #import "AppDelegate.h" #import <dispatch/dispatch.h> #import <iostream> #import <fstream> size_t fileSize = 1024 * 1024 * 10; std::ofstream *osPtr = 0; std::ifstream *isPtr = 0; @implementation AppDelegate
#import "AppDelegate.h"
#import <dispatch/dispatch.h>
#import <iostream>
#import <fstream>
size_t fileSize = 1024 * 1024 * 10;
std::ofstream *osPtr = 0;
std::ifstream *isPtr = 0;
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
const float framerate = 40;
const float frequency = 1.0f/framerate;
[NSTimer scheduledTimerWithTimeInterval:frequency
target:self selector:@selector(doSomething)
userInfo:nil repeats:YES];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
std::ofstream os("myFile", std::ios::binary);
if (os) {
osPtr = &os;
for (int i = 0; i<fileSize; i++) {
os << 'c';
}
osPtr = 0;
os.close();
printf("write done\n");
}
std::ifstream is("myFile", std::ios::binary);
if (is) {
is.seekg(0, std::ifstream::end);
fileSize = (size_t)is.tellg();
is.seekg(0, std::ifstream::beg);
isPtr = &is;
while ( is.good() )
{
char c;
is >> c;
}
isPtr = 0;
is.close();
printf("read done\n");
}
});
}
- (void)doSomething
{
// write file progress indicator
if (osPtr)
printf("%5.1f\n", (float)osPtr->tellp()/fileSize*100.0f);
// read file progress indicator
if (isPtr)
printf("%5.1f\n", (float)isPtr->tellg()/fileSize*100.0f);
}
@end
#导入“AppDelegate.h”
#进口
#进口
#进口
大小\u t fileSize=1024*1024*10;
std::ofstream*osPtr=0;
std::ifstream*isPtr=0;
@实现AppDelegate
-(无效)ApplicationIDFinishLaunching:(NSNotification*)通知
{
//在此处插入代码以初始化应用程序
常量浮点帧率=40;
常量浮点频率=1.0f/帧速率;
[NSTimer scheduledTimerWithTimeInterval:频率
目标:自选择器:@selector(doSomething)
userInfo:nil repeats:YES];
调度异步(调度获取全局队列(调度队列优先级默认为0)^{
流操作系统的std::of(“myFile”,std::ios::binary);
如果(操作系统){
osPtr=&os;
对于(int i=0;i c;
}
isPtr=0;
is.close();
printf(“读取完成\n”);
}
});
}
-(无效)剂量
{
//写入文件进度指示器
如果(osPtr)
printf(“%5.1f\n”,(float)osPtr->tellp()/fileSize*100.0f);
//读取文件进度指示器
如果(isPtr)
printf(“%5.1f\n”,(float)isPtr->tellg()/fileSize*100.0f);
}
@结束
它写的是ok,但是当读取大文件(5MB或更多)时,在streambuf类代码中会抛出EXEC_BAD_访问错误
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
typename basic_streambuf<_CharT, _Traits>::int_type
basic_streambuf<_CharT, _Traits>::sbumpc()
{
if (__ninp_ == __einp_)
return uflow();
return traits_type::to_int_type(*__ninp_++); //<---EXEC_BAD_ACCESS
}
模板
内联\u LIBCPP\u内联\u可见性
typename基本流buf::int\u类型
基本流程buf::sbumpc()
{
如果(\uuuninp\uu=\ uuuuuueinp)
返回uflow();
return traits_type::to_int_type(*u ninp_++)//stream的std::of的文档是否说它是线程安全的?我不这么认为
我敢打赌,如果在osPtr或isPtr存在时调用进度函数,您总是会遇到崩溃。但对于小文件,写入/读取速度太快,以至于在调用进度方法之前,它们都消失了。所以这就是我的方法
我需要将std::streambuf子类化,即使它可能会被过度杀戮(如发布或删除),至少对于多线程应用程序中非常常见的功能而言。异步读写文件的最佳方法是使用GCD IO函数
有一个方便的读取功能(和一个类似的写入功能)
每当系统准备好读取一些数据时,处理程序
块就会被回调,您可以更新进度指示器
您可以对同一队列使用dispatch\u after
,它们将自动序列化(只要您使用串行队列)
但是,需要明确的是:您的问题是同时从多个线程访问流对象。一个线程正在运行队列代码块,另一个线程正在运行计时器调用。它们都试图访问相同的流对象。坏消息
如果您想继续使用IO方法,需要以多种方式串行化Access。您可以创建一个类,它可以跨多个线程安全地访问IoFor,或者您可以用锁序列化Access。C++和Obj-C都提供许多同步API。
然而,在许多apple代码中使用了一个非常常见的习惯用法:委托
在您的情况下,一个简单的进度委托,加上一个发送当前进度的方法,就足够了。这样就可以从长时间运行的任务的上下文中调用该委托,这意味着您可以同步访问任何共享数据
如果你想要,你可以用GCD把任何GUI工作发送到主线程。< /P>它与GDC有关?为什么是IOS标签?这是C++为什么只有iOS和GCD标记的问题?一个常见的“背景线程与主线程UI指示”模式使用GCD是DexCuffyAsic(DeXCHOGGETBEXBROWATEL GROUP(…),^),^{/*文件加载材料/;调度异步(调度获取主队列(),^{/UI更新/进度指示材料*/});但我不清楚是否适合您的需要。您是如何创建后台线程的,是否使用NSThread
的(iOS/Mac)或者,在一个C++环境中,可以使用一个pthRead?MutX来同步。在Objto-C环境中,你可能会使用@同步。@ AaronGolden创建一个新的COCOA应用程序,只是为了测试读写进度指示器,但是它仍然抛出一个异常。请确保你所说的实际上是发生了什么。EXEC_BAD_ACCESS是一个信号,而不是一个异常。这只是你平常的日常崩溃。异常是一些代码主动检测到有问题并抛出异常。这段代码不会抛出异常。我再次声明:这与gcd无关,与ios和osx关系很小。标记是无用的,我有点理解听你说,让我绕着它转,做一些测试。
void dispatch_read(
dispatch_fd_t fd,
size_t length,
dispatch_queue_t queue,
void (^handler)(dispatch_data_t data, int error));