Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 从Obj-C中的单独线程监视ifstream读取进度_Objective C_Multithreading_Grand Central Dispatch_Ifstream - Fatal编程技术网

Objective c 从Obj-C中的单独线程监视ifstream读取进度

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

这是我使用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

- (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));